Skip to content

Files

Latest commit

 

History

History
363 lines (239 loc) · 25.1 KB

File metadata and controls

363 lines (239 loc) · 25.1 KB

一、为开发构配置 Kubernetes

欢迎来到开发者 Kubernetes】!本章从帮助您安装工具开始,这些工具将允许您在开发中利用 Kubernetes。一旦安装完毕,我们将与这些工具进行一些交互,以验证它们是否正常工作。然后,我们将回顾一些您想要理解的基本概念,以便作为开发人员有效地使用 Kubernetes。我们将在 Kubernetes 中介绍以下关键资源:

  • 容器
  • 豆荚
  • 结节
  • 部署
  • replication set-复制集

发展需要什么

除了您通常的编辑和编程工具之外,您还想安装软件来利用 Kubernetes。这本书的重点是让您在本地开发机器上做所有事情,同时如果您需要更多资源,还允许您在未来扩展和利用远程 Kubernetes 集群。Kubernetes 的一个好处是,它以同样的方式对待一台或一百台计算机,允许您利用软件所需的资源,并始终如一地做到这一点,无论它们位于何处。

本书中的示例将在本地机器的终端中使用命令行工具。第一个将是kubectl,它与 Kubernetes 集群通信。我们将使用一个运行在您自己的 Minikube 开发系统上的单机小型 Kubernetes 集群。我建议安装 Docker 的社区版,这使得构建在 Kubernetes 中使用的容器变得很容易:

可选工具

除了kubectlminikubedocker之外,您可能还想利用其他有用的库和命令行工具。

jq是一个命令行 JSON 处理器,可以轻松解析更复杂数据结构中的结果。我会把它描述为 grep 的表弟,更擅长处理 JSON 结果。您可以按照https://stedolan.github.io/jq/download/.的说明安装jq更多关于jq做什么以及如何使用的详细信息也可以在https://stedolan.github.io/jq/manual/找到。

启动并运行本地集群

一旦安装了 Minikube 和 Kubectl,就可以启动并运行一个集群。了解您正在使用的工具的版本是值得的,因为 Kubernetes 是一个相当快速的项目,如果您需要从社区获得帮助,了解这些通用工具的哪些版本将非常重要。

我写这篇文章时使用的 Minikube 和kubectl版本是:

  • 迷你立方:0.22.3 版

  • kubectl:1 . 8 . 0 版本

您可以使用以下命令检查副本的版本:

minikube version

这将输出一个版本:

minikube version: v0.22.3

如果您还没有按照安装说明进行安装,请使用 Minikube 启动 Kubernetes。最简单的方法是使用以下命令:

minikube start

这将下载一个虚拟机映像并启动它,并在其上运行 Kubernetes,作为一个单机集群。输出如下所示:

Downloading Minikube ISO
 106.36 MB / 106.36 MB [============================================] 100.00% 0s
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.

Minikube 会自动创建kubectl访问集群和控制集群所需的文件。完成此操作后,您可以获取有关集群的信息,以验证它是否已启动并正在运行。

首先可以直接问minikube它的状态:

minikube status
minikube: Running
cluster: Running
kubectl: Correctly Configured: pointing to minikube-vm at 192.168.64.2

如果我们询问kubectl它的版本,它会报告客户端的版本和与之通信的集群的版本:

kubectl version

第一个输出是kubectl客户端的版本:

Client Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.5", GitCommit:"17d7182a7ccbb167074be7a87f0a68bd00d58d97", GitTreeState:"clean", BuildDate:"2017-08-31T19:32:26Z", GoVersion:"go1.9", Compiler:"gc", Platform:"darwin/amd64"}

紧接着,它将在您的集群上传达并报告 Kubernetes 的版本:

Server Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.5", GitCommit:"17d7182a7ccbb167074be7a87f0a68bd00d58d97", GitTreeState:"clean", BuildDate:"2017-09-11T21:52:19Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}

我们也可以使用kubectl来询问关于集群的信息:

kubectl cluster-info

看到类似下面的东西:

Kubernetes master is running at https://192.168.64.2:8443

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

该命令主要让您知道正在与之通信的应用编程接口服务器已经启动并正在运行。我们可以使用附加命令来询问关键内部组件的具体状态:

kubectl get componentstatuses
NAME                 STATUS    MESSAGE              ERROR
scheduler            Healthy   ok
etcd-0               Healthy   {"health": "true"}
controller-manager   Healthy   ok

Kubernetes 还报告和存储了许多您可以请求查看的事件。这些显示了集群中正在发生的情况:

kubectl get events
LASTSEEN   FIRSTSEEN   COUNT     NAME       KIND      SUBOBJECT   TYPE      REASON                    SOURCE                 MESSAGE
2m         2m          1         minikube   Node                  Normal    Starting                  kubelet, minikube      Starting kubelet.
2m         2m          2         minikube   Node                  Normal    NodeHasSufficientDisk     kubelet, minikube      Node minikube status is now: NodeHasSufficientDisk
2m         2m          2         minikube   Node                  Normal    NodeHasSufficientMemory   kubelet, minikube      Node minikube status is now: NodeHasSufficientMemory
2m         2m          2         minikube   Node                  Normal    NodeHasNoDiskPressure     kubelet, minikube      Node minikube status is now: NodeHasNoDiskPressure
2m         2m          1         minikube   Node                  Normal    NodeAllocatableEnforced   kubelet, minikube      Updated Node Allocatable limit across pods
2m         2m          1         minikube   Node                  Normal    Starting                  kube-proxy, minikube   Starting kube-proxy.
2m         2m          1         minikube   Node                  Normal    RegisteredNode            controllermanager      Node minikube event: Registered Node minikube in NodeController

重置并重新启动集群

如果您想清除您的本地 Minikube 集群并重新启动,这是非常容易做到的。向deletestart发出命令,Minikube 将清除环境并将其重置为空白:

minikube delete Deleting local Kubernetes cluster...
Machine deleted.

minikube start
Starting local Kubernetes v1.7.5 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Connecting to cluster...
Setting up kubeconfig...
Starting cluster components...
Kubectl is now configured to use the cluster.

查看 Minikube 内置和附带的功能

使用 Minikube,您可以通过一个命令为 Kubernetes 集群打开一个基于网络的仪表板:

minikube dashboard

这将打开一个浏览器,并向您显示一个到 Kubernetes 集群的网络界面。如果您查看浏览器窗口中的 URL 地址,您会发现它指向的 IP 地址与之前从kubectl cluster-info命令返回的相同,在端口30000上运行。仪表板在 Kubernetes 内部运行,它不是唯一运行的东西。

Kubernetes 是自托管的,因为 Kubernetes 的支持部分(如仪表板、域名系统等)都在 Kubernetes 中运行。您可以通过询问集群中所有 Pods 的状态来查看所有这些组件的状态:

kubectl get pods --all-namespaces
NAMESPACE     NAME                          READY     STATUS    RESTARTS   AGE
kube-system   kube-addon-manager-minikube   1/1       Running   0          6m
kube-system   kube-dns-910330662-6pctd      3/3       Running   0          6m
kube-system   kubernetes-dashboard-91nmv    1/1       Running   0          6m

请注意,我们在此命令中使用了--all-namespaces选项。默认情况下,kubectl将只显示默认命名空间中的 Kubernetes 资源。因为我们自己没有运行任何东西,如果我们调用kubectl get pods我们只会得到一个空列表。豆荚不是 Kubernetes 人唯一的资源;您可以询问相当多不同的资源,其中一些我将在本章后面描述,更多内容将在后续章节中介绍。

现在,再调用一个命令来获取服务列表:

kubectl get services --all-namespaces

这将输出所有服务:

NAMESPACE     NAME                   CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
default       kubernetes             10.0.0.1     <none>        443/TCP         3m
kube-system   kube-dns               10.0.0.10    <none>        53/UDP,53/TCP   2m
kube-system   kubernetes-dashboard   10.0.0.147   <nodes>       80:30000/TCP    2m

注意名为kubernetes-dashboard的服务有一个Cluster-IP值,端口为80:30000。该端口配置表明,在支持kubernetes-dashboard服务的 Pods 中,它会将任何请求从端口30000转发到容器内的端口80。您可能已经注意到,集群 IP 的 IP 地址与我们之前在kubectl cluster-info命令中看到的 Kubernetes 主节点的 IP 地址非常不同。

重要的是要知道,Kubernetes 内的所有东西都运行在一个私有的、隔离的网络上,通常不能从集群外部访问。我们将在以后的章节中详细讨论这个问题。现在,请注意minikube中有一些额外的特殊配置来显示仪表板。

正在验证 Docker

Kubernetes 支持多种运行容器的方式,Docker 是最常见的,也是最方便的。在本书中,我们将使用 Docker 来帮助我们创建将在 Kubernetes 中运行的映像。

您可以通过运行以下命令来查看您安装了哪个版本的 Docker,并验证它是否可以运行:

docker  version

kubectl一样,它会报告docker客户端版本以及服务器版本,您的输出可能如下所示:

Client:
 Version: 17.09.0-ce
 API version: 1.32
 Go version: go1.8.3
 Git commit: afdb6d4
 Built: Tue Sep 26 22:40:09 2017
 OS/Arch: darwin/amd64
Server:
 Version: 17.09.0-ce
 API version: 1.32 (minimum version 1.12)
 Go version: go1.8.3
 Git commit: afdb6d4
 Built: Tue Sep 26 22:45:38 2017
 OS/Arch: linux/amd64
 Experimental: false

使用docker images命令,可以看到本地有哪些容器映像可用,使用docker pull命令,可以请求特定的映像。在下一章的示例中,我们将在 alpine container 映像的基础上构建我们的软件,因此让我们继续获取该映像,以验证您的环境是否正常工作:

docker pull alpine 
Using default tag: latest
latest: Pulling from library/alpine
Digest: sha256:f006ecbb824d87947d0b51ab8488634bf69fe4094959d935c0c103f4820a417d
Status: Image is up to date for alpine:latest

然后,您可以使用以下命令查看映像:

docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 76da55c8019d 3 weeks ago 3.97MB</strong>

If you get an error when trying to pull the alpine image, it may mean that you are required to work through a proxy, or otherwise have constrained access to the internet to pull images as you need. You may need to review Docker's information on how to set up and use a proxy if you are in this situation.

清除和清理 Docker 映像

因为我们将使用 Docker 来构建容器映像,所以知道如何去除映像将是非常有用的。您已经看到了带有docker image命令的映像列表。还有隐藏在输出中的由 Docker 维护的中间映像。要查看 Docker 存储的所有映像,请使用以下命令:

docker images -a

如果您只按照前面的文本提取了阿尔卑斯山的映像,您可能不会看到任何额外的映像,但是当您在下一章构建映像时,这个列表将会增长。

您可以使用docker rmi命令和映像名称来移除映像。默认情况下,Docker 将尝试维护容器最近使用或引用的映像。因此,您可能需要强制删除来清理映像。

如果你想重置和删除所有的映像并重新开始,有一个方便的命令可以做到这一点。通过将 Docker 映像和docker rmi捆绑在一起,我们可以要求它强制移除它所知道的所有映像:

docker rmi -f $(docker images -a -q)

立方概念容器

Kubernetes(以及这个领域的其他技术)都是关于管理和编排容器的。容器实际上是一个包装在一组 Linux 技术周围的名称,其中最突出的两个是容器映像格式和 Linux 利用 cgroups 将进程相互隔离的方式。

出于所有实际目的,当有人谈到容器时,他们通常暗示有一个运行单个进程所需的一切的映像。在这种情况下,容器不仅是映像,而且是关于调用什么和如何运行它的信息。容器还表现得像拥有自己的网络访问权限。实际上,它是由运行容器的 Linux 操作系统共享的。

当我们想要编写在 Kubernetes 下运行的代码时,我们将总是谈论将其打包并准备在容器中运行。本书后面更复杂的例子将利用多个容器一起工作。

It is quite possible to run more than a single process inside a container, but that's generally frowned upon as a container is ideally suited to represent a single process and how to invoke it, and shouldn't be considered the same thing as a full virtual machine.

如果您通常使用 Python 开发,那么您可能熟悉使用类似pip的东西来下载您需要的库和模块,并且您使用类似于python your_file的命令来调用您的程序。如果您是节点开发人员,那么您更有可能熟悉npmyarn来安装您需要的依赖项,并且您使用node your_file运行您的代码。

如果你想把这些都打包起来并在另一台机器上运行,你可能需要重做所有下载库和运行代码的指令,或者压缩整个目录并把它移到你想运行它的地方。容器是一种将所有信息收集到一个映像中的方法,这样就可以轻松地在 Linux 操作系统上移动、安装和运行。该规范最初由 Docker 创建,现在由开放容器倡议(OCI)(https://www.opencontainers.org)维护。

虽然容器是 Kubernetes 的最小构件,但 Kubernetes 使用的最小单元是 Pod。

库资源 pod

Pod 是 Kubernetes 管理的最小单元,也是构建系统其余部分的基本单元。创建 Kubernetes 的团队发现,让开发人员指定哪些进程应该始终在同一个操作系统上一起运行是值得的,并且一起运行的进程的组合应该是被调度、运行和管理的单元。

在本章的前面,您看到了 Kubernetes 的一个基本实例,它的一些软件在 Pods 中运行。Kubernetes 的大部分是使用这些相同的概念和抽象运行的,允许 Kubernetes 自行托管自己的软件。运行 Kubernetes 集群的一些软件是在集群本身之外管理的,但是越来越多地利用 Pods 的概念,包括 DNS 服务、仪表板和控制器管理器,它们通过 Kubernetes 协调所有的控制操作。

Pod 由一个或多个容器以及与这些容器相关的信息组成。当您向 Kubernetes 询问 Pod 时,它将返回一个数据结构,其中包括一个或多个容器的列表,以及 Kubernetes 用来协调 Pod 和其他 Pod 的各种元数据,以及当程序失败时 Kubernetes 应该如何行动和反应的策略,被要求重新启动等等。元数据还可以定义诸如相似性之类的东西,这影响了 Pod 在集群中的调度位置、对如何获取容器映像的期望等等。重要的是要知道,Pod 并不打算被视为一个持久、长寿的实体。

它们被创造和毁灭,本质上是短暂的。这允许包含在控制器中的独立逻辑来管理诸如规模和可用性等职责。正是这种职责分离使 Kubernetes 能够在出现故障时提供自我修复的方法,并提供一些自动扩展功能。

Kubernetes 运行的 Pod 有几个具体的保证:

  • Pod 的所有容器都将在同一个节点上运行
  • 在一个 Pod 中运行的任何容器都将与同一 Pod 中的任何其他容器共享节点的网络
  • Pod 中的容器可以通过附加到容器的卷共享文件
  • Pod 具有明确的生命周期,并且将始终保留在启动它的节点上

实际上,当您想知道 Kubernetes 集群上运行的是什么时,您通常会想知道 Kubernetes 内运行的 Pods 及其状态。

Kubernetes 维护和报告 Pod 的状态,以及组成 Pod 的每个容器的状态。容器的状态为RunningTerminatedWaiting。Pod 的生命周期有点复杂,由一个严格定义的阶段和一组 PodStatus 组成。阶段是PendingRunningSucceededFailedUnknown中的一个,一个阶段所包含内容的具体细节记录在https://kubernetes . io/docs/concepts/workloads/pod-life cycle/# pod-Phase中。

Pod 还可以包含探测器,探测器会主动检查容器中的一些状态信息。Kubernetes 控制器部署和使用的两个常见探针是一个livenessProbe和一个readinessProbe。活动探测器定义容器是否启动并运行。如果不是,Kubernetes 中的基础设施会杀死相关的容器,然后应用为 Pod 定义的重启策略。readinessProbe表示容器是否准备好服务请求。readinessProbe的结果与其他 Kubernetes 机制结合使用,例如服务(我们将在后面详述)将流量转发到相关容器。一般来说,探测器被设置成允许容器中的软件向 Kubernetes 提供反馈循环。您可以在https://kubernetes . io/docs/concepts/workloads/pods/pod-life cycle/# container-projects上找到更多关于 projects、如何定义它们以及如何使用它们的详细信息。我们将在以后的章节中详细探讨探测器。

命名空间

Pods 被收集到名称空间中,这些名称空间用于将 Pods 分组在一起以实现各种目的。当我们之前使用--all-namespaces选项询问集群中所有 Pods 的状态时,您已经看到了一个名称空间的例子。

命名空间可用于提供资源使用的配额和限制,对 Kubernetes 在集群内部创建的 DNS 名称有影响,并且在未来可能会影响访问控制策略。如果在通过kubectl与 Kubernetes 交互时没有指定名称空间,则该命令假定您使用的是名为default的默认名称空间。

为豆荚和容器编写代码

成功使用 Kubernetes 的关键之一是考虑您希望您的代码如何操作,并对其进行结构化,使其干净地适合 Pods 和 Containers 的结构。通过构建您的软件解决方案,将问题分解为在 Kubernetes 提供的约束和保证下运行的组件,您可以轻松地利用并行性和容器编排来无缝地使用多台机器,就像使用单台机器一样。

Kubernetes 提供的保证和抽象反映了谷歌(和其他公司)多年来在大规模、可靠和冗余地运行其软件和服务方面的经验,利用横向扩展模式来解决大规模问题。

库资源节点

节点是添加到 Kubernetes 集群的机器,通常运行 Linux。它可以是物理机或虚拟机。在minikube的情况下,是单个虚拟机在运行 Kubernetes 的所有软件。在较大的 Kubernetes 集群中,您可能有一台或多台机器专门用于管理集群和运行工作负载的单独机器。Kubernetes 通过跟踪节点的资源使用、调度、启动(如果需要,重新启动)Pods,以及协调将 Pods 连接在一起或将其暴露在集群之外的其他机制来管理其资源。

节点可以(并且确实)具有与其相关联的元数据,以便 Kubernetes 能够意识到相关的差异,并且能够在调度和运行 Pods 时解释这些差异。Kubernetes 可以支持各种各样的机器协同工作,并在所有机器上高效运行软件,或者将 Pods 调度限制在只有具有所需资源的机器上(例如,GPU)。

网络

我们之前提到过,Pod 中的所有容器共享 Node 的网络。此外,Kubernetes 集群中的所有节点都应该相互连接,并共享一个专用的集群范围网络。当 Kubernetes 在 Pod 中运行容器时,它是在这个隔离的网络中运行的。Kubernetes 负责处理 IP 地址,创建 DNS 条目,并确保一个 Pod 可以与同一 Kubernetes 集群中的另一个 Pod 通信。

另一个资源,服务,我们将在后面深入研究,是 Kubernetes 用来通过这个私有网络向其他 Pods 公开或者处理集群内外的连接。默认情况下,运行在这个私有隔离网络中的 Pod 不会暴露在 Kubernetes 集群之外。根据您的 Kubernetes 集群是如何创建的,有多种途径可以从集群外部打开对您的软件的访问,稍后我们将详细介绍包含负载平衡器、节点端口和入口的服务。

控制器

Kubernetes 的构建理念是,你告诉它你想要什么,它知道如何去做。当您与 Kubernetes 交互时,您声称您希望一个或多个资源处于特定的状态,具有特定的版本,等等。控制器是大脑存在的地方,用于跟踪这些资源,并试图运行您所描述的软件。这些描述可以包括运行多少个容器映像副本、更新 Pod 中运行的软件版本,以及处理意外丢失部分集群的节点故障情况。

Kubernetes 中使用了各种各样的控制器,它们大多隐藏在我们将进一步挖掘的两个关键资源后面:部署和复制集。

库资源复制集

一个复制集包装了 Pods,定义了需要并行运行的数量。复制集通常由部署依次包装。副本集通常不直接使用,但对于表示水平缩放至关重要,它表示要运行的并行 Pods 的数量。

复制集与一个 Pod 相关联,并指示该 Pod 应该在集群中运行多少个实例。副本集还意味着 Kubernetes 有一个控制器,可以监视正在进行的状态,并知道有多少个 Pod 要继续运行。这就是 Kubernetes 真正开始为您工作的地方,如果您在一个复制集中指定了三个 Pod,而一个失败了,Kubernetes 将自动为您安排并运行另一个 Pod。

Kubernetes 资源–部署

在 Kubernetes 上运行代码最常见和推荐的方法是部署,它由部署控制器管理。我们将在下一章和后面的章节中探讨部署,既可以直接指定它们,也可以使用kubectl run等命令隐式创建它们。

豆荚本身是有趣的,但也是有限的,特别是因为它是短暂的。如果一个节点死亡(或断电),该节点上的所有 Pods 将停止运行。复制集提供自我修复能力。集群内的工作,以识别何时一个 Pod 不再可用,并将尝试安排另一个 Pod,通常是使服务恢复在线,或以其他方式继续工作。

部署控制器包装并扩展了复制集控制器,主要负责推出软件更新,并在您使用软件的新版本更新部署资源时管理推出过程。部署控制器包括元数据设置,以了解要保持运行的 Pods 数量,以便您可以通过添加容器的新版本并在请求时停止旧版本来实现软件的无缝滚动更新。

代表 Kubernetes 资源

Kubernetes 资源通常可以表示为 JSON 或 YAML 数据结构。Kubernetes 是专门构建的,您可以保存这些文件,当您想要运行您的软件时,您可以使用kubectl deploy等命令并提供您之前创建的定义,它使用这些定义来运行您的软件。在我们的下一章中,我们将开始展示这些资源的具体示例,并构建它们供我们使用。

当我们进入下一章和以后章节的例子时,我们将使用 YAML 描述我们的资源,并通过kubectl以 JSON 格式请求数据。所有这些数据结构都是为 Kubernetes 的每个版本正式定义的,还有 Kubernetes 提供的用于操作它们的 REST APIs。所有 Kubernetes 资源的正式定义在源代码控制中用 OpenAPI(也称为swag)维护,可在https://github . com/Kubernetes/Kubernetes/tree/master/API/swag-spec查看。

摘要

在这一章中,我们安装了minikubekubectl,并使用它们来启动一个本地 Kubernetes 集群并与之进行短暂的交互。然后,我们浏览了一些我们将在未来章节中使用和深入探索的关键概念,包括容器、Pod、节点、部署和复制集。

在下一章中,我们将深入探讨如何将您的软件放入容器中,以及如何在您自己的项目中设置它的技巧。我们将浏览 Python 中的一个示例,以及 Node.js 中的另一个示例,您可以将其用作自己代码的起点。