Kubernetes教程:容器编排入门
本文由 Ryan Thelin 撰写,最初发表于Educative.io。
Kubernetes 是一款功能强大但又复杂的工具,乍看之下可能难以理解。本文将对其进行深入剖析,解释其核心功能、支持工具和独特特性。最后,为了更好地理解这些概念,我们将通过一个循序渐进的演示,展示如何使用 Kubernetes 创建基本程序。对于那些考虑从事 DevOps 职业的人来说,这是一篇很好的教程。
本次研讨会将涵盖以下内容:
什么是Kubernetes?
Kubernetes 是一个开源容器管理平台,用于部署和管理容器化工作负载。这些容器化工作负载是许多现代 Web 应用的基石,它们将应用程序及其依赖项打包在一起,统一交付和存储。容器化的优势在于一致性;用户无需考虑或构建应用程序所需的依赖项,因此应用程序在运行时始终保持相同的行为。
虽然无需 Kubernetes 等管理平台也能实现容器部署,但这些容器协同工作时的行为可能不稳定。例如,运行时,某个容器可能会占用过多机器资源,导致其他容器资源不足。这些资源不足的容器可能会因此崩溃,由于没有其他程序管理它们,也没有备份,这种情况会一直持续到程序重新启动为止。
简而言之,容器需要大量的微观管理,从分配给每个容器的资源量到故障容器的自我修复。值得庆幸的是,Kubernetes 能够定制和处理所有这些幕后任务!
Docker 和 Kubernetes
如果说 Kubernetes 是调度器,负责管理每个容器的协同工作,那么 Docker 就是招聘器,为你提供所需的所有容器。简而言之,Docker 提供的两个主要工具分别是Docker Desktop和 Docker Hub。Docker Desktop 供开发者轻松创建和共享容器化应用程序,而Docker Hub则是一个在线库,其中包含大量由社区创建的即用型容器模板,称为“镜像”。Docker 也可以运行容器,但它缺乏维护所需状态、建立容器间连接以及其他许多运行多个容器所必需的功能的工具。
Docker 和 Kubernetes 的真正威力只有在二者结合时才能得以展现。首先,利用 Docker,我们可以创建应用程序并将其打包成容器,通过拉取预先创建的容器镜像来解决一些常见问题。然后,我们可以在 Kubernetes 中运行这些容器,Kubernetes 将管理底层容器的执行,并维护应用程序的理想运行环境。在整个流程中,这些应用程序始终将用户的易用性放在首位,从而将曾经需要频繁人工干预的容器运行任务,转变为高度精简和自动化的流程。
Kubernetes 基本概念
现在我们对 Kubernetes 有了大致的了解,也对其最重要的合作伙伴 Docker 有了一些了解,但真正上手之后,Kubernetes 究竟是什么样子呢?下面我们将详细介绍任何 Kubernetes 应用的基本组件,并展示它们是如何相互构建的。我们还会介绍一些其他工具,它们肯定会对你有所帮助。
豆荚
Pod 是 Kubernetes 中最小的应用程序单元。Pod 代表应用程序的单个独立实例及其运行所需的资源,每个 Pod 都有自己的 IP 地址。Pod 由一个或多个容器组成,这些容器在同一节点上协同工作并共享生命周期;每个 Pod 可以由一个或多个容器组成,具体取决于其复杂程度。这样做的好处是,同一 Pod 内的所有容器无需用户进行额外设置即可相互通信。
然而,这些 pod 彼此高度隔离,无法单独与其他 pod 通信。这就需要我们引入下一个组件——服务。
服务
服务是一种抽象层,位于 Pod 之上,充当各个 Pod 与外部世界之间的桥梁。由于 Pod 是相互隔离的实例,它们通常无法相互访问。服务通过定义访问策略(类似于准入条件)来解决这个问题,该策略适用于由选择器决定的特定 Pod 集合。一旦完成此操作,该服务集合中的 Pod 就可以自由通信,直到访问策略发生更改。
在创建复杂且相互依赖的程序时,服务也十分便捷,因为它们会为服务内的所有 Pod 设置一个统一的域名系统 (DNS) 记录。程序的另一部分(部署,见下文)可以使用此 DNS 名称访问这些 Pod 的信息,而无需了解每个 Pod 的 IP 地址。换句话说,程序的另一部分可以通过共享的 DNS 记录连接到此 Pod 组,而无需跟踪每个 Pod 的状态或信息。这通过隔离性为程序提供了更大的灵活性,因为可以在服务组中添加或删除 Pod,而无需修改部署。
部署
Kubernetes 的最后一个组件——部署(Deployment),简化了 Pod 的升级过程。通常,升级系统时,需要关闭所有旧实例,然后使用升级后的实例重启系统,这会导致一段时间的停机。Kubernetes 的部署机制允许我们通过“滚动更新”来规避这个问题。在滚动更新过程中,Pod 会被逐个关闭,升级到新版本,并在确认功能正常后再进行下一个 Pod 的升级。这样一来,Kubernetes 不仅确保了零停机时间,还保证了每个 Pod 都能按预期升级。如果新程序出现错误,还可以反向重复此过程,自动回滚到之前的版本。
要更详细地了解 Pod、Service、Deployment 和 Replication Controller,请查看我们之前关于 Kubernetes 的文章。
迷你库贝
Minikube 是我们推出的首款附加工具,它能为您的所有容器化程序创建一个虚拟测试环境。运行时,Minikube 会在您的计算机上创建一个虚拟机 (VM),模拟物理系统的行为,而无需担心对您的计算机造成任何意外更改。该虚拟机是一个简单的单节点集群,也就是说,它的行为类似于一组计算机,但只连接了一台计算机。这种简化的集群形式和模拟行为使 Minikube 成为未完成程序开发和测试的理想环境,也适合初学者学习基于容器的编程。
虽然这对于 Linux 和 Mac 用户来说非常理想,但 Windows 用户可能难以启动。对于 Windows 用户,建议尝试使用 Docker Desktop;它具有相同的测试环境功能,并且更容易集成到 Windows 基础架构中。
kubectl
接下来要介绍的工具是 kubectl,这是一个用于管理 Kubernetes 集群的命令行应用程序。从很多方面来看,kubectl 命令本身就像一门独立的编程语言,拥有独特的语法和复杂的语法结构。虽然由于其功能强大且复杂,kubectl 上手难度较高,但它为开发者提供了无与伦比的控制力,使其成为目前最流行的 Kubernetes 集群管理工具。结合 Minikube,这两个工具对于想要深入学习 Kubernetes 的用户来说至关重要。
Kubernetes 集群
集群是由一组服务器组成的系统,它们协同工作以实现同一目标。这些服务器通常被称为节点,每个节点都可以执行独立的任务,最终共同完成系统的目标。每个集群的配置文件中都定义了一系列运行条件,这些条件是集群正常运行所必需的,称为“期望状态”。期望状态可能包含诸如正在运行的工作负载、集群需要访问的容器镜像,以及特定机器上应具备的硬件资源等具体要求。
主节点和工作节点
集群中的节点功能各异;有些是主节点,有些是工作节点。每个集群中都至少有一个主节点和至少一个工作节点。
主节点负责维护集群的预期状态,释放资源,检查各项条件的状态等等。它还负责管理集群中各个节点上 Pod 的调度,合理分配任务,确保所有节点都能正常运行,避免过载。主节点包含多个组件,例如 API 服务器、控制器管理器、调度器和 ETCD。
工作节点负责运行程序的所有其他环节,承担大部分繁重的工作。这些节点上可以运行多个 Pod,每个 Pod 都按照主节点的分配执行任务。由于工作节点之间基本相互隔离,因此可以轻松扩展集群,增加工作节点数量而不会出现问题。
继续学习。
无需费力浏览视频或文档,即可轻松学习 Kubernetes。Educative 的文字课程易于快速浏览,并提供实时编码环境,让学习变得快捷高效。
Kubernetes 的强大功能
目前为止,我们仅仅探索了 Kubernetes 最基本的功能,它还有许多其他特性和功能等待您进一步学习。随着组织对容器的使用规模不断扩大,面临的问题也越来越复杂,这些特性和功能的重要性也会日益凸显。以下列举了一些您可以利用的特性,以最大限度地发挥 Kubernetes 的优势:
- 自我修复能力以维持“理想状态”
- 自动扩缩容功能可以根据 CPU 利用率或其他应用程序提供的指标自动更改正在运行的容器数量。
- 可通过加载模块扩展其他功能
- 管理集群内应用程序可用的存储空间
- 允许通过秘密标签存储机密信息
- 轻松访问日志和背景信息
- 跨节点自动负载均衡
- 优化元件布局,以提高硬件效率
- 节点能力管理,以便将具有特定节点要求的组件(例如需要 GPU 硬件的应用程序)运行在具有所需能力的节点上。
- 通过副本控制器和放置策略实现可扩展性
- 定制自动化部署和回滚策略
通过Viktor Farcic 的课程“高级 Kubernetes 技术:监控、日志记录、自动扩展” ,进一步探索这些功能。
Kubernetes教程:实战演练
现在,我们将学习如何使用 Kubernetes 创建我们的第一个容器化程序。要跟随本教程操作,您需要 kubectl 和 Docker Desktop(Windows 系统)或 Minikube(Mac 和 Linux 系统)。后续步骤中,您还需要 curl,因为它允许您通过命令行发送 Web 请求。
虽然并非必需,但许多用户会发现包管理器比手动安装这些工具更方便。使用包管理器,安装新软件包只需一条命令。Windows 用户的最佳包管理器选择是 Chocolatey,Mac 和 Linux 用户的最佳选择是 Homebrew。
-
有关安装 kubectl 的说明,请访问 Kubernetes 博客(此处链接)。
-
要了解更多关于 Docker 的信息并获取 Docker Desktop 的安装说明,请访问我们之前的文章。安装完成后,别忘了启用 Kubernetes!
-
有关安装 minikube 的说明,请访问Kubernetes 博客上的此页面。
-
要安装 curl,请按照curl 网站上的这些说明进行操作。
要打开我们的工作区,Windows 用户需要以管理员身份运行 PowerShell 程序(该程序应该默认安装),Mac 用户需要打开命令行,Linux 用户需要打开终端。这将打开一个命令行窗口,我们将在本教程中输入命令。
现在一切就绪,让我们开始吧!
创建 Kubernetes 集群
首先,我们将创建集群。借助 Minikube 或 Docker Desktop 等工具,这非常简单。这是唯一一个因工具不同而输入内容有所差异的步骤。
Minikube 用户,请输入:
///minikube start///
Docker Desktop 集群已自动启动。
现在,为了测试我们的集群是否创建正确,请输入:
///kubectl get svc///
表格将以如下形式打印。您的表格可能略有不同,但最左侧的两个字段(///Kubernetes///和///clusterIP///)将相同。
///
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6s
///
这表明默认服务///Kubernetes///当前正在运行。由于该服务总是在集群启动时初始化,因此我们知道集群正在按预期运行!
部署应用程序
现在我们将创建第一个部署。为此,我们将从 Google Container Registry (GCR) 拉取一个名为 `<image_name>` 的测试镜像///hello-node///。创建此部署后,将内置一个 Pod。
为此,请粘贴以下代码行:
///kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node///
现在,要检查此部署是否正常运行,请输入:
///kubectl get deployments///
///
NAME READY UP-TO-DATE AVAILABLE AGE
hello-node 1/1 1 1 170m
///
这将打印当前在此集群上运行的部署列表。由于我们只创建了一个部署,因此您只会看到///hello-node///列表中的这一个。
恭喜,您的应用程序已成功部署!
探索您的应用
既然我们已经有了,不妨四处看看!我们将使用///get///命令来检查我们上面学到的所有部分是否都已存在于我们的应用程序中并正常运行!
首先,我们来看一下节点,输入:
///kubectl get nodes///
///
NAME STATUS ROLES AGE VERSION
docker-desktop Ready master 1d2h v1.15.5
///
这将列出集群中所有节点的名称、状态和角色。由于我们的集群只是一个单设备测试环境,因此只会显示一个节点。
现在我们来看看我们的舱体,请进:
///kubectl get pods///
同样,屏幕上会打印出一个包含一些有用信息的表格。
///
NAME READY STATUS RESTARTS AGE
hello-node-55b49fb9f8-wwpwr 1/1 Running 0 36s
///
这里需要注意的是,我们的 pod 只有一个实例,如列所示///1/1///。///ready///我们还可以从列中看到它当前正在运行///status///,这表明它没有发生故障。
因此,该///get pods///命令在排查更复杂系统的故障时非常有用,因为它允许您查看众多 pod 中的哪一个出现故障。
如果您需要更多信息,还可以使用///describe///命令针对特定的 pod、节点甚至部署来查看每个资源的大量可用信息。
让我们在部署中尝试一下,输入:
///kubectl describe deployment hello-node///
///
Name: hello-node
Namespace: default
CreationTimestamp: Mon, 01 Jan 2020 19:26:58 -0700
Labels: app=hello-node
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=hello-node
Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=hello-node
Containers:
hello-node:
Image: gcr.io/hello-minikube-zero-install/hello-node
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: hello-node-55b49fb9f8 (1/1 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 95s deployment-controller Scaled up replica set hello-node-55b49fb9f8 to 1
///
如果你是 Kubernetes 新手,可能对这些信息不太熟悉;但对于经验丰富的 Kubernetes 用户来说,这种便捷的信息访问方式正是 Kubernetes 如此吸引人的原因之一。有了 `npm run dev`///get///和 ` npm ///describe///run build` 命令,所有排查故障所需的信息都触手可及!
公开您的应用
到目前为止,我们的应用程序一直完全隔离在测试环境中。但在实际应用中,几乎总是需要让应用程序向其他外部 Web 应用程序发送 Web 请求。为此,我们将使用一个///expose///命令,该命令会创建一个与部署名称相同的新服务实例,并自动配置端口以允许连接。在该命令中,我们指定服务应该监听的端口。在本例中,我们将使用端口 8080。
要亲自尝试一下,请输入:
///kubectl expose deployment hello-node --type=LoadBalancer --port=8080///
要查看此服务的实际运行情况,我们可以再次输入:
///kubectl get svc///
///
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-node LoadBalancer 10.108.188.234 localhost 8080:32505/TCP 7s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1h
///
这里我们可以看到,原本只有一个服务的地方,现在有了两个:原服务///kubernetes///和新服务///hello-node///。请注意,由于新服务是公开的,因此它在 `<name>` 和 ` ///EXTERNAL-IP///<name>`///PORT(S)///字段上都与原服务有所不同。`NodePorts` 是已发布的 IP 地址,供外部用户访问这些服务。
现在我们的应用程序已经公开,我们可以访问hello-nodepod 内运行的 Web 应用程序来打印消息。
为此,请输入:
/// curl http:///localhost:8080 ///
///Hello World!///
就这样,我们调用了一个外部 IP 地址来执行我们的 pod 并让它打印了结果!
扩展您的应用
虽然我们的应用程序现在功能齐全,并且可以被外部访问,但如果我们的 pod 发生故障会发生什么情况?或者,如果到达我们程序的请求数量突然激增会发生什么情况?
为了应对这些情况,我们需要扩展应用程序;创建更多 Pod 实例///hello-node///来分配请求,或在某个 Pod 发生故障时进行接管。最棒的是,使用 Kubernetes,只需一条命令即可创建实例,之后上述操作将自动完成!
要扩展我们的应用程序,请输入:
kubectl scale --replicas=3 deployment/hello-node
这将使我们的程序保持三个 pod 实例正在运行的状态,///hello-node///而不是只有一个。
要进行检查,请输入:
///kubectl get deployment hello-node///
这应该会打印出类似这样的屏幕截图:
///
NAME READY UP-TO-DATE AVAILABLE AGE
hello-node 3/3 3 3 135m
///
请注意列中列出的此部署下的三个 pod ///ready///。
或者,要单独查看各个舱室,您可以进入:
///kubectl get pods///
///
NAME READY STATUS RESTARTS AGE
hello-node-55b49fb9f8-fxjnj 1/1 Running 0 2m34s
hello-node-55b49fb9f8-jlfwq 1/1 Running 0 2m34s
hello-node-55b49fb9f8-zhf9f 1/1 Running 0 136m
///
这再次表明,原本只有一个 pod 的地方,现在有了三个独立但完全相同的///hello-node///pod 实例。
正在更新您的应用
最后,我们知道没有哪个应用会永远占据主导地位;最终,新版本会取代旧版本。就我们而言,假设我们///hello-node///创建了一个新版本的 Pod,并且想要用它来替换所有旧 Pod。正如我们之前讨论过的,Kubernetes 可以满足我们的需求,因为我们可以使用滚动更新来实现零停机升级。
由于没有新版本///hello-node///,如果输入此内容将会显示错误消息。
但是,如果有更新版本,您可以通过输入以下方式应用它:
///kubectl set image deployments/hello-node hello-node=myContainers/hello-node:v2///
为了更清晰地说明这一点,我们首先标记要设置新镜像,然后指定要适配的类型(部署),接着指定要适配的部署。///hello-node///在第一次提及部署之后,我们就告诉了命令要编辑的内容,此时我们再提供新镜像///myContainers/hello-node:v2///。
Kubernetes 会逐个关闭旧 Pod,并用升级后的版本替换它们。这个过程需要一些时间,具体时间取决于需要升级的 Pod 数量。
要检查升级是否成功,我们可以输入:
/// kubectl rollout status deployments/hello-node///
如果完成,则会返回:
/// deployment "hello-node" successfully rolled out///
至此,我们已经完成了 Kubernetes 基础程序的创建和探索。要完成你的杰作,现在只需输入以下两行代码:
///
kubectl delete service hello-node
kubectl delete deployment hello-node
///
这将清理您的系统,并使您的系统为您的下一个 Kubernetes 项目做好准备!
结论:Kubernetes 完全指南
Kubernetes 的学习难度较高,通常需要几天才能上手,几年才能精通。不过,好消息是,您不必独自面对这段学习之路!由 Kubernetes 专家 Viktor Farcic 设计的课程涵盖了各个级别的学习内容,无论您是初学者还是希望提升技能的专家,都能找到适合自己的课程!如果您渴望成为一名 DevOps 专业人士,我强烈建议您了解一下我们的学习路径:面向开发者的 DevOps。该路径包含以下课程:
- 软件工程师计算机网络知识入门
- 面向开发者的 Docker
- Kubernetes实用指南
- Kubernetes高级技术:日志记录、监控、自动扩缩容
这些课程将帮助你成为DevOps领域的佼佼者。
更多资源
想更深入了解 Kubernetes 的各个组成部分吗?请查看我们之前的一些文章,其中对它们进行了详细介绍。
- 为什么(以及何时)使用 Kubernetes
- Docker 和 Kubernetes 入门指南
- 在 Kubernetes 上部署我的第一个服务:揭秘 Ingress
- Pod、服务、部署……我应该在什么情况下使用它们?
实用工具
软件包管理器:
- Windows:https://chocolatey.org/
- Mac 和 Linux:https://brew.sh/
软件包下载链接
- https://www.docker.com/products/docker-desktop
- https://kubernetes.io/docs/tasks/tools/install-minikube/
- https://kubernetes.io/docs/tasks/tools/install-kubectl/
- https://curl.haxx.se/download.html