Alan Hou的个人博客

精通Docker第三版 – 第九章 Docker和Kubernetes

《精通Docker第三版》完整目录:

第一章 Docker概览
第二章 创建容器镜像
第三章 存储和发布镜像
第四章 管理容器
第五章 Docker Compose
第六章 Windows容器
第七章 Docker Machine
第八章 Docker Swarm
第九章 Docker和Kubernetes
第十章 在公有云上运行Docker
第十一章 Portainer – 一个Docker的GUI
第十二章 Docker安全
第十三章 Docker工作流
第十四章 Docker进阶

本章中,我们一起来看Kubernetes。和Docker Swarm相似,我们可以使用Kubernetes来创建和管理用于运行基于容器的应用集群。

本章涵盖的主要内容有:

技术准备

Docker中的Kubernetes只支由Docker for Mac和Docker for Windows支持。和此前章节一样,作者将使用自己偏好的操作系统macOS。同样,其中极少数据的支持命令可能只在macOS中使用。

观看如下视频来查看代码的实时操作:

Kubernetes简介

如果你有了解容器,那么总会在某个地方碰到Kubernetes,在Docker桌面软件中启动它之前,我们先花点时间了解下Kubernetes的前世今身。

Kubernetes(音koo-ber-net-eez)来自给予舵手或船长的希腊名称。Kubernetes(也称为K8s),是一个起源于Google的开源项目,允许我们自动化部署、管理和扩容容器化应用。

Google的容器简史

Google对于Linux容器解决方案的研究历时已久。2016年迈出了第一步,开发Linux内核称作控制组(cgroups)的功能。这一功能于2008年合并到了Linux发行版2.6.24的内核中。该功能让我们可以隔离资源,如CPU、RAM、网络和磁盘I/O,或一个或多个进程。控制组仍然是Linux容器的核心组成并为Docker及其它容器工具所使用。

Google接着以名为lmctfy的容器栈涉足容器领域,它是Let Me Contain That For You的缩写。这是LXC的工具集和库的一个替代。这是 Google 内部在自己应用内用于管理容器的工具的一个开源版本。

译者注:LXC 表示 Linux Container,即 Linux 容器。

接着Google再次成为容器使用新闻热点是在2014年5月的Gluecon上Joe Beda进行讲话之后 。在讲话期间,Beda透露Google当时几乎所有业务都基于容器,以及他们每周会启动近20亿个容器。并声称这一数字并不包含长期运行的容器,也就是说这些容器都是供短期使用的。但是进行快速的数学计算之后,这表示Google平均每秒会启动3000个容器。

在讲话的后半段,Beda提及Google使用了调度器这样他们无需每周手动管理20亿个容器,或担心容器在哪里启动乃至容器的可用性。

Google还发布了一篇名为Large-scale cluster management at Google with Borg(Google 使用 Borg 进行大规模集群的管理)的论文。该论文不仅让Google以外的人知道了他们使用的调度器的名称,Borg,还深入到了在设计调度器时做设计决策的细节。

该论文也提到了他们的内部工具,Google在容器运行集群中运行面向用户的应用,如 Google Docs、Gmail和Google 搜索,都是由Borg进行管理。

Borg使用电视节目星际迷航:下一代的外星种族Borg来进行命名。在电视节目中,Borg是一种半机械生物,它们的文明基于称为“集合体”的集体意识。这使他们不仅可以共享相同的想法,同时通过子空间网络,确保每个集合体的成员透过集体意识给予指导和监督。相信你也会同意,Borg种族的特征与我们希望运行的容器集群匹配度极高。

Borg在Google内部使用了好几年,最终由名为Omega的调试器替代。大约是这个时候Google声明会拿出一些Borg的核心功能,将其重塑为一个开源项目。这个项目内部称之为Seven,由多名Borg的核心贡献人员操刀。目标在于创建一个版本更为友好的Borg,脱离Google自己的内部流程和工作方式。

Seven,取名自星际迷航:航海家号中的人物,九之七(Seven of Nine)是从集合体中解放出来的博格个体,最终在首次对外提交时使用了Kubernetes这一名称。

Kubernetes概览

那么,现在我们知道了Kubernetes的由来,可以更深入的挖掘Kubernetes是什么了。该项目的大部分,确切地说是88.5%,由 Go 语言编写,这不足为奇,因为Go在2011年开源之前是由Google内部开发的一种编程语言。此项目的其它部分文件由Python和Shell帮助脚本和HTML文档组成。

一个典型的Kubernetes集群由角色为master或node服务器组成。你可以对这两种角色的节点进行单独安装。

master角色是神奇发生的地方,同时也是集群的大脑。它负责决定在何处启动pod,并且监控集群本身以及集群内运行的pod的健康状况。我们在了解了这两个角色之后会来讨论pod。

通常,核心组件会部署到角色分配为master的主机上:

上面讲解了管理组件,下面需要讨论它们所管理的内容是什么。node由如下组件构成:

你可能注意到了到此我们没提到容器。这是因为Kubernetes实际上不直接与容器进行交互,它与pod进行通讯。把pod看作一个完整的应用,有点像我们使用Docker Compose启动多个容器的应用。

Kubernetes和Docker

Kubernetes最早被视作Docker自己的集群技术Docker Swarm的竞品。但通过这几年的发展,Kubernetes实际上已成为容器编排的标准了。

所有主流云提供商都提供Kubernetes即服务。有如下这些:

表面上,所有这些主流玩家支持Kubernetes可能并没有什么了不起的。但别忘了我们可以在跨多平台部署容器化应用并保持一致性。以前,这些平台被称作后花园,与它们交互的方式非常的不同。

在Docker在2017年10月初次发表声明时普遍表示惊讶,但尘埃落定时又是那么的理所当然。使用Docker for Mac和Docker for Windows为开发人员提供可以在本地操作应用,然后使用Docker企业版来部署和管理自己的Kubernetes集群,甚至是使用前述的一种云服务,与我们在第一章 Docker概览中讨论的“像在本机操作”非常契合。

下面我们来看如何在Docker软件中启动Kubernetes支持并进一步的进行使用。

启动Kubernetes

Docker上Kubernetes的安装过程极为简单。启动Kubernetes支持,我们只需要打开Preferences并点击Kubernetes选项卡:

可以看到,有三个主选项。勾选Enable Kubernetes复选框,然后选择Deploy Docker Stacks to Kubernetes by default。先不勾选Show systems containers,我们会在启动服务后再来看更多的细节。点击Apply会弹出如下信息:

点击Install按钮会下载所需的容器来在Docker软件上启动Kubernetes的支持:

像前面的一个对话框中所提示的那样,Docker会需要不些时间来进行下载、配置和启动该集群。完成后,你会看到Kubernetes is running旁边有绿点:

打开Terminal并运行如下命令:

正常运行后不会显示任何容器。运行如下命令:

这会列出Kubernetes相关的镜像:

这些镜像的源为Docker和Google容器仓库(k8s.gcr.io)所提供的官方Kubernetes。

你可能已经猜到,勾选Show system containers (advanced)复选框,然后运行以下命令会列出在本地Docker软件上启动Kubernetes服务所有运行的容器:

因为运行上述命令会有大量输出,以下仅显示容器的名称。通过运行如下命令来进行实现:

运行该命令会得到如下输出:

有18个运行中的容器,这也是存在隐藏它们的原因。可以看到几乎所有我们在前一部分讨论的组件以及其它一些提供Docker集成的组件。我会推荐不勾选Show system containers的选项,因为我们不需要在每次查看运行中的容器时看到这18个容器。

这里另一件需要注意的事情是Kubernetes的菜单项中有内容了。这一菜单可用于在Kubernetes集群间进行切换。因为当前我们只有一个活跃的集群,因此只列出了一个:

现在我们本地的Kubernetes已启动并运行,下面就开始使用它吧。

使用Kubernetes

我们已经在Docker桌面软件上启动和运行了Kubernetes集群,可以开始与其进行交互了。先来看与Docker桌面组件一起安装的命令kubectl。

前面已提到,kubectl同时进行了安装。如下命令会显示客户端及其所连接到的集群的相关信息:

接下来运行如下命令来看kubectl是否能识别到我们的node:

既然我们已经有了与node进行交互的客户端,就可以通过运行如下命令来查看在Kubernetes中默认配置的命名空间:

然后通过如下命令来在命名空间中查看pod:

Kubernetes中的命名空间是集群内隔离资源的一种很好的方式。可以在Terminal的输出中看到,集群内有四个命名空间。有default命名空间,通常为空。两个主Kubernetes服务的命名空间:docker和kube-system。这些包含组成我们集群的pod以及最后一个命名空间,kube-public,类似default,为空。

在我们启动自己的pod之前,先快速地查看下如何与我们运行的pod进行交互,首先了解如何查找我们pod的更多信息:

以上命令会打印出kube-scheduler-docker-for-desktop这一pod的明细信息。你可能注意到我们需要使用–namespace 来传递命名空间。如果不传递,那么kubectl会默认使用没有名为kube-scheduler-docker-for-desktop在运行的default命名空间。

该命令的完整输出如下所示:

可以看到有关这一pod的大量信息,包含容器列表,我们只有一个,名为kube-scheduler。我们还可以看到镜像所使用的容器ID,容器启动使用的标记,以及Kubernetes调度器用于启动和维护该pod的数据。

我们已经知道了容器名,可以开始与其进行交互。例如,运行如下命令会打印出我们这一容器的日志:

运行如下命令会获取pod中的每个容器的日志:

类似Docker,你还可以对pod和容器执行命令。例如,如下命令会运行uname -a 命令:

小贴士:确保在如下两个命令的 — 后添加空格。不加的话会产生报错。

同样,我们可以对指定名称的容器或pod中的所有容器运行该命令:

我们再来通过安装和向基于 web 的仪表盘记录日志来进一步了解Kubernetes。虽然Docker默认并不包含,通过Kubernetes项目提供的定义文件来安装非常之简单。我们只需要运行如下命令:

服务和部署创建之后,会需要几分钟来进行启动。你可以通过运行如下命令来查看状态:

在输出像下面这样时,仪表盘就安装并准备好了:

此时我们的仪表盘已处于运行中,我们要找到一种访问它的方式。这可以通过kubectl中内置的proxy服务。仅需运行如下命令来将其启动:

这会启动proxy,打开浏览器访问http://127.0.0.1:8001/version/会显示集群的相关信息:

但我们想要看的是仪表盘。可通过http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/来进行访问。

首次在浏览器中打开这个URL时会出现登录界面。因为我们是通过proxy来访问仪表盘的,仅需点击SKIP按钮:

译者注:新版的 Kubernetes 强制要求输出验证信息,没有再发现 SKIP 按钮,可通过如下命令来进行测试的 Token

登录之后,就可以看到集群上的很多信息了:

现在我们的集群已经启动并运行了,我们可以启动一些示例应用。

Kubernetes和其它Docker工具

在启动Kubernetes时,我们选择了将Kubernetes作为Docker的stack命令的默认编排器。前一章中,Docker的stack会在Docker Swarm中启动我们的Docker Compose文件。我们所使用的Docker Compose文件像下面这样:

我们在Kubernetes上启动应用之前,需要做一些微调并删除placement,修改后文件的内容如下:

编辑了该文件之后,运行如下命令就会启动栈:

可以看到,Docker会等待栈可用后再回到命令提示符。我们还可以运行在Docker Swarm上启动栈后查看栈相关信息相同的命令:

我们还可以使用kubectl来查看一些细节:

你可能注意到我们并不需要提供命名空间。这是因为我们的栈在默认命名空间中启动。同时,在列出服务时,会列出集群栈的集群 ClusterIP和LoadBalancer。查看LoadBalancer,你可以看到其外部 IP 为localhost、端口为80。

在浏览器中打开http://localhost/会显示该应用:

如果你的仪表盘还在打开的话,可以查看栈,甚至是打开其中一个容器的Terminal:

如果你的仪表盘还在打开的话,可以查看栈,甚至是打开其中一个容器的Terminal:

你可以通过运行如下命令来删除该栈:

最后再提一点,你可能会想,太好了,我可以在Kubernetes集群的任何地方运行我的 Docker Compose文件了。额,严格意义上说并不是这样的。我们说到,在第一次启动Kubernetes时,启动了一些Docker组件。它们确保Docker尽可能紧密地进行集成。但是,这些组件在非Docker管理的集群中并不存在,因此你会无法使用docker stack命令。

并非没有补救措施。Kubernetes项目中提供了一个名为Kompose工具,可接收一个Docker Compose 文件并将其实时转化为一个Kubernetes定义文件。

要在macOS上安装Kompose,运行如下命令:

Windows 10的用户可以使用 Chocolatey来安装这一二进制:

ℹ️Chocolatey是一个基于命令行的包管理器,可用于在Windows机器上安装各类软件包,与在Linux机器上使用yum或apt-get或者macOS上使用brew相似。

最后,Linux用户可以运行如下命令:

安装完成后,可以通过运行如下命令来启动你的Docker Compose文件:

你会得到类似下面的输出:

根据输出中的提示,运行如下命令会给出刚刚启动的服务和pod的细节信息:

你可以通过运行如下命令来删除这些服务和pod:

虽然你可以使用kompose up和kompose down,我会建议生成Kubernetes定义文件并对它们按需进行修改。只需运行如下命令:

这会生成pod和服务文件:

你会看到Docker Compose文件和生成的两个文件之间有相当大的不同。cluster-pod.yaml文件类似下面这样:

cluster-service.yaml文件类似下面这样:

然后你可以通过运行如下命令来启动这些文件:

要删除该集群的pod和服务,我们只需要运行如下命令即可:

虽然在后面的章节还会使用到Kubernetes,建议还是先在Docker桌面软件中先取消对Kubernetes的集成,因为它在空闲时会带来一些系统资源占用。只需取消勾选Enable Kubernetes即可。点击Apply时,Docker会停止所有运行Kubernetes所需的容器,但它不会删除这些镜像,这样在你重新启动它时可以很快的完成。

总结

本章中,我们通过Docker桌面软件来学习了Kubernetes。Kubernetes的内容远不止本章中所讲解的这些,所以千万不要觉得它只有这些。在讨论了Kubernetes起源之后,我们看了如何使用Docker for Mac或Docker for Windows在本地机器上启动它。

然后我们讨论了kubectl的基本使用,接着学习像Docker Swarm那样使用docker stack启动并运行应用。

本章的最后,我们讨论了Kompose,它是Kubernetes项目下的一个工具。帮助我们将Docker Compose文件转化为Kubernetes所用的文件,让我们可以将应用迁移到纯Kubernetes上。

下一章中,我们将来学习公有云上的Docker,比如Amazon Web Services,并简短地再次使用Kubernetes。

课后问题

扩展阅读

本章开始处提及的一些Google工具、PPT 和白皮书参见如下链接:

本章说涉及到的云服务的详细信息参见:

以下可以查看到Docker有关对于Kubernetes支持的声明:

最后,Kompose的主页为:

退出移动版