我写了一本库伯内斯入门指南

2020-05-31 12:13:06

在这个关于Kubernetes的多部分系列文章中,我将尝试捕捉到我认为每个想要与Kubernetes一起学习和工作的人都应该知道的内容。

如果你读过我以前的任何一篇文章或课程,你就会知道我喜欢通过实际例子来学习和授课。尽管我非常喜欢实际的例子,但是在Kubernetes中有很多术语和概念是您需要理解的。但我向您保证,一旦您阅读完整个系列,您就会理解这些概念,并能够运行使用Kubernetes中的数据库的应用程序或服务。

如果您是云原生的初学者,您可能希望查看我的Docker初学者指南文章,以获得对Docker的基本了解。不过别担心,即使你不知道多克,你也会跟着去的。

在关于了解Kubernetes的系列文章的第一部分中,我将介绍以下主题:

阅读本文并浏览示例后,您将了解什么是Kubernetes,并了解Kubernetes构建块和资源(如Pod、部署和服务)。

这是一篇理论与实践相结合的文章。如果你按照实际例子去做,你会从这篇文章中得到最大的收获。为此,您需要以下工具:

您可以选择多个选项。现实世界中最多的选择是从云提供商那里获得Kubernetes集群。然而,由于多种原因,这可能不是每个人的选择。

下一个最佳选择是在您的计算机上运行Kubernetes集群。假设您有一些空闲的内存和CPU,您可以使用以下工具之一在您的计算机上运行单节点Kubernetes集群:

老实说,你可以选择上面的任何一个选项。创建Kubernetes副本集、部署和Pod可以在其中任何一个上运行。您也可以创建Kubernetes服务,但是,例如,当您尝试使用LoadBalancer服务类型时,事情就会变得有点复杂。

使用云管理的集群,创建LoadBalancer服务类型将创建负载平衡器的实际实例,并且您将获得可用于访问服务的外部/公共IP地址。

上面列表中最接近模拟LoadBalancer服务类型的一个解决方案是Docker Desktop。使用Docker Desktop,您的服务将在外部IP localhost上公开。您也可以使用Kind和Minikube访问这些服务,但是,它需要您运行其他命令。

为此,我将在本文中使用Docker Desktop。您可以按照各自网站上所有选件的安装说明进行操作。

在您安装了这些工具之一之后,请确保您下载了Kubernetes CLI。这是一个名为kubectl的单一二进制文件,它允许您对集群运行命令。要确保一切正常工作,可以运行kubectl get Nodes列出Kubernetes集群中的所有节点。您应该会得到类似于以下内容的输出:

您还可以检查上下文是否正确设置为docker-ktop。Kubernetes使用一个名为config的配置文件来查找连接到集群所需的信息。此文件位于您的主文件夹中-例如$HOME/.kube/config。上下文是该配置文件中的一个元素,它包含对集群、命名空间和用户的引用。如果您正在访问或运行单个群集,则配置文件中只有一个上下文。但是,您可以定义指向不同群集的多个上下文。

使用kubectl config命令,您可以查看这些上下文并在它们之间切换。您可以运行current-context命令查看当前上下文:

还有其他命令,如use-context、set-context、view-context等。我更喜欢使用一个叫kubectx的工具。此工具允许您在不同的Kubernetes上下文之间快速切换。例如,如果我在配置文件中设置了三个集群(上下文),则运行kubectx会输出以下内容:

运行该命令时,当前选定的上下文也会高亮显示。要切换到Minikube上下文,我可以运行:kubectx Minikube。

可以使用kubectl运行的等效命令是kubectl config get-context查看所有上下文,kubectl config use-context Minikube切换上下文。

在继续之前,如果您正在使用Docker for Mac/Windows,请确保您的上下文设置为docker-ktop。

这些天来,集装箱随处可见。Docker等工具可用于打包从应用程序到数据库的所有内容。随着微服务体系结构的日益普及和脱离单一的应用程序,一个单一的应用程序现在是多个较小服务的集合。

管理单个应用程序有其自身的问题和挑战,更不用说管理必须协同工作的数十个较小的服务了。您需要一种方法来自动化和管理您的部署,弄清楚如何扩展各个服务,如何使用网络并将它们连接起来,等等。

这就是容器编排的用武之地。容器编排可以帮助您管理容器的生命周期。使用容器业务流程系统允许您执行以下操作:

集装箱管弦乐团的几个例子是马拉松、码头群和我今天要谈到的库伯内斯(Kubernetes)。

Kubernetes是一个开源项目,也是集群管理和调度以容器为中心的工作负载的流行选择之一。您可以使用Kubernetes来运行您的容器,进行零宕机部署,在这种部署中,您可以在不影响用户的情况下更新您的应用程序,以及许多其他很酷的东西。

通常,你会看到库伯内斯被称为K8&34;。K8S是Kubernetes的代名词。第一个(K)和最后一个字母(S)是单词Kubernetes中的第一个和最后一个字母,8是这两个字母之间的字符数。其他流行的数字名有代表国际化的数字符号";i18n&34;或代表可访问性的数字符号";a11y&34;。

我已经看到关于库伯内斯和多克的问题,以及两者之间的不同之处。使用Docker,您可以打包您的应用程序。此包称为镜像或Docker镜像。您可以将图像视为模板。使用Docker,您可以从您的镜像创建容器。例如,如果您的Docker映像包含Go二进制或Java应用程序,则容器是该应用程序的运行实例。如果您想了解更多关于Docker的信息,请查看Docker入门指南。

另一方面,Kubernetes是一个容器编排工具,它知道如何管理Docker(和其他)容器。Kubernetes使用更高级别的构造(如Pods)来包装Docker(或其他)容器,并让您能够管理它们。

码头群是一个容器编排工具,就像Kubernetes一样。您可以使用它来管理Docker容器。使用Sarm,您可以将多个Docker主机连接到一个虚拟主机。然后,您可以使用Docker CLI一次与多个主机对话,并在其上运行Docker容器。

Kubernetes集群是运行您的容器化应用程序所需的一组物理或虚拟机以及其他基础设施资源。Kubernetes集群中的每台机器都称为节点。每个Kubernetes群集中有两种类型的节点:

主节点上的一个主要组件称为API服务器。API服务器是您在创建Kubernetes资源或管理群集时Kubernetes CLI(Kubectl)与之对话的端点。

调度器组件与API服务器协同工作,以将应用程序或工作负载调度到工作节点上。它还了解节点上可用的资源以及工作负载请求的资源。使用此信息,它可以决定您的工作负载最终位于哪些工作节点上。

Kube控制器管理器运行多个控制器进程。这些控制器监视集群的状态,并尝试使集群的当前状态(例如,正在运行工作负载A";的副本)与所需状态(例如,我想要10个正在运行的工作负载A";的副本)保持一致。控制器包括节点控制器、复制控制器、端点控制器以及服务帐户和令牌控制器。

云控制器管理器运行特定于云提供商的控制器,并且可以管理群集外部的资源。只有当您的Kubernetes集群在云中运行时,此控制器才会运行。如果您正在计算机上运行Kubernetes群集,则此控制器将不会运行。此控制器的目的是让群集与云提供商对话,以管理节点、负载均衡器或路由。

最后,etcd是分布式键值存储。Kubernetes集群和API对象的状态存储在etcd中。

就像在主节点上一样,工作节点也有不同的组件在运行。第一个是库贝莱特。该服务在每个工作节点上运行,其任务是管理容器。它确保集装箱正常运行,并连接回控制平面。Kubelet与API服务器通信,负责管理运行它的节点上的资源。

当向集群中添加新的工作节点时,kubelet会自我介绍并提供其拥有的资源(例如";I有X个CPU和Y个内存";)。然后,它询问是否需要运行任何容器。您可以将kubelet视为工作节点管理器。

Kubelet使用容器运行时接口(CRI)与容器运行时通信。容器运行时负责使用容器。除了Docker,Kubernetes还支持其他容器运行时,比如tainerd或cri-o。

容器在Pod内运行,由上图中的蓝色矩形表示(容器是每个Pod内的红色矩形)。Pod是可以在Kubernetes群集上创建、调度和管理的最小可部署单元。Pod是组成应用程序的容器的逻辑集合。运行在同一个Pod内的容器还共享网络和存储空间。

每个工作节点还具有一个代理,该代理充当在工作节点上运行的工作负载的网络代理和负载平衡器。通过外部负载均衡器传入的客户端请求将通过这些代理重定向到Pod内部运行的容器。

Kubernetes API定义了许多称为资源的对象,例如名称空间、Pod、服务、秘密、配置映射等。

当然,您也可以使用自定义资源定义(CRD)定义您自己的自定义资源。

在配置了Kubernetes CLI和集群之后,您应该尝试并运行kubectl API-resources命令。它将列出所有定义的资源-将会有很多资源。

Kubernetes中的资源可以使用YAML定义。YAML(YAML标记语言)通常用于配置文件和。它是JSON格式的超集,也就是说您也可以使用JSON来描述Kubernetes资源。

每个Kubernetes资源都有apiVersion和Kind字段,用于描述您在创建资源时使用的Kubernetes API版本(例如,app/v1)以及要创建的资源类型(例如,Deployment、Pod、Service等)。

元数据包括有助于标识您正在创建的资源的数据。这通常包括名称(例如myDeployment)和将在其中创建资源的名称空间。您还可以在元数据中提供其他字段,如标签和注释,以及在创建资源后添加的几个字段(例如,creationTimestamp)。

Pod可能是Kubernetes中最常见的资源之一。它们是一个或多个容器的集合。Pod内的容器共享相同的网络和存储。这意味着同一pod中的任何容器都可以通过localhost相互通信。

豆荚的设计是短暂的,这意味着它们的持续时间非常短。Pod可以随时重新调度为在不同节点上运行。这意味着每当重新启动Pod时,您的容器也将重新启动。

创建后,每个Pod都会分配一个唯一的IP地址。Pod内的容器可以侦听不同的端口。要访问您的容器,您可以使用Pod的IP地址。使用上图中的示例,您可以运行curl 10.1.0.1:3000与一个容器通信,运行curl 10.1.0.1:5000与另一个容器通信。但是,如果您想在容器之间对话-例如,从底部调用顶部容器,您可以使用http://localhost:3000.

如果您的Pod重新启动,它将获得不同的IP地址。因此,您不能依赖IP地址。直接通过IP与您的Pod通话不是正确的方式。

称为Kubernetes服务的抽象是您可以用来与Pod通信的东西。Kubernetes服务为您提供稳定的IP地址和DNS名称。我稍后会谈到服务。

Pod中的所有容器都一起缩放。下图显示了从一个Pod扩展到四个Pod的效果。请注意,您不能缩放Pod中的单个容器。豆荚是刻度的单位。

";太棒了!我可以在同一个Pod中运行我的应用程序和数据库!!";不!不要那样做。

首先,在大多数情况下,数据库的伸缩率不会与应用程序的伸缩率相同。请记住,您正在缩放一个豆荚和该豆荚内的所有容器,而不仅仅是单个容器。

其次,在Kubernetes中运行有状态工作负载(如数据库)不同于运行无状态工作负载。例如,您需要确保Pod重新启动之间的数据是持久的,并且重新启动的Pod与重新启动的Pod具有相同的网络标识。可以使用持久卷和状态集等资源来实现这一点。稍后我将更多地讨论如何在Kubernetes中运行有状态工作负载。

通常,您不应该手动创建豆荚。你可以做这件事,但你真的不应该。原因是,如果吊舱崩溃或被删除,它将永远消失。

apiVersion:V1 Kind:Pod Metadata:Name:Hello-Pod Labels:App:Hello spec:Containers:-Name:Hello-Container image:busybox命令:[';sh';,';-c';,';ECHO Hello From My Container!&;&;睡眠3600';]

在前几行中,我们定义了资源类型(Pod)和元数据。元数据包括pod的名称(hello-pod)和一组简单的键值对标签(app=hello)。

在规范部分中,我们描述了Pod应该是什么样子。我们在这个pod中将有一个名为hello-tainer的单一容器,它将运行名为busybox的映像。容器启动后,将执行命令字段中定义的命令。

要创建Pod,您可以将上面的YAML保存到一个名为pod.yaml的文件中,例如。然后,您可以使用Kubernetes CLI(Kubectl)创建实例:

Kubernetes使用创建的资源类型和名称进行响应。您可以使用kubectl get pods来获取运行集群默认名称空间的所有pod的列表。

您可以使用logs命令查看Pod内部运行的容器的输出:

如果您有多个容器在同一pod内运行,您可以使用-c标志指定要从中获取日志的容器名称。例如:kubectl日志hello-pod-c hello-tainer。

如果我们使用kubectl delete pod hello-pod删除此pod,该pod将永远消失。没有任何东西可以自动重新启动吊舱。如果您再次运行kubectl get Pods,您会注意到Pod不见了:

这与您想要的行为相反。如果您的工作负载在Pod中运行,您会希望它在出现错误时自动重新调度并重新启动。

为了确保崩溃的Pod重新启动,您需要一个可以管理Pod生命周期的控制器。如果您的Pod被删除或发生了不好的事情(节点关闭,Pod需要被驱逐),此控制器可确保自动重新安排它的日程。

ReplicaSet的工作是维护稳定数量的Pod拷贝或复制副本。ReplicaSet控制器可保证指定数量的相同Pod始终在运行。复制副本计数由资源定义中的复制副本字段控制。

如果您从单个Pod开始,并且希望扩展到5个Pod,则ReplicaSet控制器将使用群集中的当前状态(一个Pod),然后再创建四个Pod以满足所需的状态(5个Pod)。ReplicaSet还会关注Pod,因此如果您删除一个Pod或将其放大或缩小,它将执行必要的操作,以满足所需的复制副本数量。为了创建Pod,ReplicaSet使用Pod模板,该模板是资源定义的一部分。

apiVersion:app/v1 Kind:Replica Set Metadata:Name:Hello Labels:App:Hello spec:Replicas:5选择器:matchLabels:App:Hello Template:Metadata:Labels:App:Hello spec:Containers:-Name:Hello-Container image:busybox命令:[';sh';,';-c&39;,';从我的容器回显Hello!&;&;睡眠3600&39;]。

由ReplicaSet创建的每个Pod都可以由metadata.ownerReferences字段标识。此字段指定哪个ReplicaSet拥有Pod。如果删除了ReplicaSet拥有的任何Pod,ReplicaSet会立即通知并采取相应操作(即重新创建Pod)。

ReplicaSet还使用选择器对象和matchLabel来检查它可能拥有的任何新Pod。如果存在与选择器标签ReplicaSet匹配的新Pod,并且它没有所有者引用,或者所有者不是控制器(即,如果我们手动创建Pod),则ReplicaSet将接管它并开始控制它。

该命令将显示ReplicaSet的名称以及所需的、当前的和就绪的Pod复制副本的数量。如果列出Pod,您会注意到有5个Pod正在运行:

$kubectl get poNAME Ready状态重新启动aghello-dwx89 1/1运行0 31shello-fchvr 1/1运行0 31shello-fl6hd 1/1运行0 31shello-n667q 1/1运行0 31shello-rftkf 1/1运行0 31s

您还可以按标签列出Pod。例如,如果运行kubectl get po-l=app=hello,您将获得设置了app=hello标签的所有Pod。目前,这是我们创建的5个吊舱。

让我们再看看所有者引用字段。我们可以使用-o YAML标志来获取Kubernetes中任何对象的YAML表示。获得YAML后,我们将搜索ownerReferences字符串:

$kubectl get po hello-dwx89-o yaml|grep-a5所有者引用.。ownerReferences:-apiVersion:App/v1 block OwnerDeletion:true Controller:true Kind:ReplicaSet Name:Hello。

在ownerReferences中,所有者的名称设置为hello,种类设置为ReplicaSet。这是拥有Pod的ReplicaSet。

注意到我们是如何在命令中使用po来引用pod的吗?某些Kubernetes资源有短名称,可以用来代替全名。当您表示pod时,可以使用po;当您表示部署时,可以使用Deploy。要获取支持的短名称的完整列表,可以运行kubectl API-resources。

您将注意到的另一件事是Pod的命名方式。以前,在我们直接创建单个pod的地方,pod的名称是hello-pod,因为这是我们在YAML中指定的。这一次,在使用代表时。

..