动手动脑学Kubernetes系列之Deployment介绍

查理谈科技 2024-05-11 03:39:06

中, 介绍了搭建好的#minikube#环境,如果你现在还没有一个可用的minikube环境, 那么可以去该篇文章中直接下载;

在之前的文章中, 先后介绍了如何从源代码开始构建一个Node.js应用和Spring Boot 应用, 并且部署到Kubernetes 中(这个Kubernetes 环境主要是之前建好的#minikube#) , 现在我们开始进一步深入的学习Kubernetes, 用一个个可以实际运行的例子的形式, 深入理解#Kubernetes#的概念以及原理.

本篇是#动手动脑学Kubernetes#的第三篇, #动手动脑学Kubernetes#, 就是先动手体验, 然后再理论学习, 让你从例子中体会Kubernetes 的具体用法, 然后再去学习Kubernetes的理论知识, 达到实际操作的升华!

在#动手动脑学Kubernetes#里, 学习了Pod的基本知识;在里, 学习了标签(Label)的语法, 使用Label来选择和过滤Kubernetes 资源; 现在是第三篇, 一起来学习Deplpoyment(部署) 的使用方法吧!

从镜像开始

部署是Pod的监督者,可让您对新Pod版本的发布方式和时间以及回滚到先前状态的方式进行精细控制。

让我们创建一个名为sise-deploy的部署(deployment),该部署就像一个监工一样, 会"监督" Kubernetes 创建应用的两个pod副本(replica), 以及一个replica set, 先来看看Deployment是什么情况:

地址: https://raw.githubusercontent.com/hintcnuie/kbe/main/specs/deployments/d09.yaml

Deployment文件内容:

apiVersion: apps/v1kind: Deploymentmetadata: name: sise-deployspec: replicas: 2 selector: matchLabels: app: sise template: metadata: labels: app: sise spec: containers: - name: sise image: quay.io/openshiftlabs/simpleservice:0.5.0 ports: - containerPort: 9876 env: - name: SIMPLE_SERVICE_VERSION value: "0.9"

可以看到, 我们这个例子里面, 用的还是simpleservice 这个简单的镜像, 但是跟上一篇不一样的地方在于,我们这次在spec 里面, 把replicas设置为2,也就是说, 这个应用会有两个.

这究竟意味着啥呢?

开始Deployment!

先来部署下看看, 把代码运行起来!

kubectl apply -f https://raw.githubusercontent.com/hintcnuie/kbe/main/specs/deployments/d09.yaml

结果:

deployment.apps/sise-deploy created

看看部署情况:

kubectl get deploy

在命令返回中, 可以看出sise 已经有两个部署:

在Dashboard里面检查Deployment, 会更加直观一些.

因为这次是两个Pod, 回顾上一篇文章中对于Pod 水平复制的情况:

每个Pod 都是一个给定应用程序的一个实例(instance), 如果需要水平扩展一个应用程序的话(水平扩展, 意味着提供更多的资源, 运行更多的实例), 那么就需要扩展更多的Pod, 每个Pod 代表一个实例.

这种水平扩展, 在Kubernetes术语中称之为"复制(replication)", 复制的多个Pod会被作为一个组来创建和管理, 而管理这些组的则是工作负荷(workload)资源以及相应的控制器(controller).

我们来到Dashboard 页面, 仔细看看sise-deploy 这个Deployment资源:

除了最上面的metadata 之外, 我们在页面下半部分, 还可以看到RollingUpdate信息, 在最后一个页面, 我们看到一个Replica Set, 这究竟是什么东西呢?

ReplicaSet的目的是维护在任何给定时间运行的稳定的副本Pod集。 因此,它通常用于保证指定数量的相同Pod的可用性。

来看看我们这里用到的具体的Replica Set, 名称是sise-deploy-747848cd97的具体情况:

从上面的截图中我们也能看出, 这个名称为sise-deploy-747848cd97的Replica Set, 其metadata基本和Deployment 是一致的, 使用的选择器是app: sise 和 pod-template-hash: 747848cd97, 然后下面就是有两个Pod, 名称分别是:

sise-deploy-747848cd97-4z6qbsise-deploy-747848cd97-g67pm

这就是这个Replica Set 基本情况.

我们也可以从命令行来看到这些信息, 其中rs 就是replica set 的缩写:

kubectl get rs

结果:

从命令行里面也能看到这个Replica Set的基本信息.

我们在最开始就知道, Kubernetes 命令是这样的:kubectl [command] [type] [name] [flag]

刚才运行的kubectl get rs, get 就是其中的command, 操作命令, rs 就是里面的资源名称, 可是除了pod, rs 之外, 还有啥其他的资源? 我们怎么记得并记得住所有要操作的资源, 以及资源的缩写名称呢?

有一个kubectl api-resources 命令可以帮助你列出所有要操作的资源:

kubectl api-resources

结果:

kubectl api-resources

等等,刚才说的还是"复制的Pod 会以一个组的方式被Kubernetes 的Workload 资源以及相应的控制器(Controller) 来管理", 那就是说Pod 或者说Pod的多个副本会被Controller 来管理, 怎么现在又冒出了一个Replia Set?

而且我们从Dashboard 里面, 也看到了Replica Controller, 但是并没有看到Replica Controller 里面有任何对象存在, 这究竟是什么情况?

Deployment, Replica Set和Pod的关系

其实,这里就涉及到Replica Controller 和Replica Set 的关系了.

Replica Set

ReplicaSet是Kubernetes控制器之一,可确保我们有指定数量的Pod副本正在运行。 Kubernetes中的控制器负责执行任务,以确保集群的所需状态与观察到的状态匹配。

如果没有ReplicaSet,我们将不得不为所需的Pod数量创建多个清单,这是部署单个应用程序副本的大量工作。 在Kubernetes的早期版本中,ReplicaSet被称为Replication Controller。 两者之间的主要区别是ReplicaSets允许我们使用称为“标签选择器”的东西。

标签是用于指定对用户有意义和有用的对象属性的键值对,因此请记住,它不会改变核心系统的工作方式。 标签选择器用于识别Kubernetes中的一组对象。

ReplicaSets允许我们使用“基于集合”的标签选择器(例如,(environment in (production, qa) 或者 tier notin (frontend, backend)),而不是“基于平等”的标签选择器(例如,环境=生产环境或生产层!=前端) 是您与复制控制器一起使用的。

Replication Controller

Replication Controller是Kubernetes中复制(Replica)的原始形式。 它已被Replica Set取代,但仍在广泛使用. Replication的结构使您可以轻松地创建多个Pod,然后确保始终存在该Pod数量。 如果pod确实崩溃了,则Replication Controller会替换它。 Kubernetes控制器(例如复制控制器)还具有其他优点,例如能够扩展容器的数量以及使用单个命令更新或删除多个容器的能力。

来看一个例子:

apiVersion: v1kind: ReplicationControllermetadata:  name: soaktestrcspec:  replicas: 3  selector:    app: soaktestrc  template:    metadata:      name: soaktestrc      labels:        app: soaktestrc    spec:      containers:      - name: soaktestrc        image: nickchase/soaktest        ports:        - containerPort: 80

Kubernetes Replica Set

比较副本控制器(Replication Controller)与副本集(ReplicalSet)可能很棘手,因为后者是一种混合。 它们在某些方面比ReplicationControllers强大,而在另一些方面则不那么强大。 副本集的声明方式与ReplicationControllers基本上相同,不同之处在于它们为选择器提供了更多选项。 例如,我们可以这样创建一个ReplicaSet:

apiVersion: extensions/v1beta1 kind: ReplicaSet metadata:  name: soaktestrs spec:  replicas: 3  selector:    matchLabels:      app: soaktestrs  template:    metadata:      labels:        app: soaktestrs   environment: dev    spec:      containers:      - name: soaktestrs        image: nickchase/soaktest        ports:        - containerPort: 80

在上面这个例子里,它与Replication Controller大部分是一样的,只是使用matchLabels而不是label。

在这里,我们不会继续展开两者的比较, 只要知道, Kubernetes 官方文档里面是建议使用Kubernetes Replica Set的:

ReplicaSets是ReplicationControllers的后继者。 两者的作用相同,行为相似,不同之处在于ReplicationController不支持标签用户指南中所述的基于集合的选择器要求。 因此,ReplicaSets比ReplicationControllers更可取

而且, 当我们把Deployment, Replica Set 放在一起来整体看待Pod副本复制的时候, 我们会看到官方文档是这么说的:

部署(Deployment)是一个对象,它可以拥有Replica Set(副本集), 并且通过声明性的服务器端滚动更新来更新它们及其Pod。 尽管ReplicaSets可以独立使用,但如今,它们主要由Deployments用作协调Pod创建,删除和更新的机制。

使用部署(Deployment)时,您不必担心管理它们创建的Replica Set(副本集)。 部署拥有并管理其副本集。 因此,建议您在需要副本集时使用部署。

因此我们可以这么理解Deployment, Replica 和Pod的关系, 当Kubernete 有一个Deployment对象需要部署的时候, Deployment里面定义的Pod 的基本信息以及副本信息, Deployment 是不会去直接创建的, 而是委托给Deployment 内置的Replica Set资源, Replica Set 去负责完成和维护符合要求的Pod以及副本情况, 而Deployment并不会直接去创建Pod以及副本:

现在回到第一句,为什么说Deployment 就像是一个监工呢? 这是因为, 在Deployment文件,详细描述了所需的Pod以及数量状态,然后Deployment 内置的控制器, 也就是Replica Set,将Pod的实际状态以受控的速率, 更改为所需的状态。 可以定义部署(Deployment)以创建新的副本集,或删除现有的部署,并在新的部署中采用其所有资源。

最后, 我们来看看实际创建的Pod:

kubectl get pods --show-labels --selector 'app=sise'

结果:

NAME READY STATUS RESTARTS AGE LABELS

sise-deploy-747848cd97-4z6qb 1/1 Running 0 163m app=sise,pod-template-hash=747848cd97

sise-deploy-747848cd97-g67pm 1/1 Running 0 163m app=sise,pod-template-hash=747848cd97

从最终的Pod 名字上, 我们也能够看出这其中的关系, 从部署名称(sise-deploy)派生出Replica Set的名称(sise-deploy-747848cd97), 又从Replica Set的名称, 通过增加随机数的方式派生出Pod 的名称(sise-deploy-747848cd97-4z6qb, sise-deploy-747848cd97-g67pm)

通过滚动更新来改动Deployment

现在,在Pod中运行的sise容器配置的应用, 可以返回版本信息, 目前的版本是0.9。 让我们使用 curl进行验证:

kubectl exec sise-deploy-747848cd97-4z6qb -t -- curl -s 127.0.0.1:9876/info

因为我们并没有创建Service, 所以我们只能单独指定一个Pod 来运行, 这里我们选择的是第一个, 在这个Pod的容器里面运行curl 命令, 结果:

{"host": "127.0.0.1:9876", "version": "0.9", "from": "127.0.0.1"}

结果中我们可以看到调用是成功的.

下面我们来更新一下Deployment , 让这个返回结果显示1.0, 首先我们来看一下新的Deployment文件:

Deployment 文件地址: https://raw.githubusercontent.com/hintcnuie/kbe/main/specs/deployments/d10.yaml

内容:

apiVersion: apps/v1kind: Deploymentmetadata: name: sise-deployspec: replicas: 2 selector: matchLabels: app: sise template: metadata: labels: app: sise spec: containers: - name: sise image: quay.io/openshiftlabs/simpleservice:0.5.0 ports: - containerPort: 9876 env: - name: SIMPLE_SERVICE_VERSION value: "1.0"

注意, 我们在env中定义了一个变量SIMPLE_SERVICE_VERSION, 这个变量的值就是1.0, 下面我们来更新Deployment:

kubectl apply -f https://raw.githubusercontent.com/hintcnuie/kbe/main/specs/deployments/d10.yaml

看看执行的结果:

因为国内访问github网站, 有时候会比较慢, 所以在读取github的时候, 在右边的命令行窗口多次查询Kubernetes中Pod 的情况, 在第一次的返回结果中, Pod 是没有变化的, 可以看见在第二次查询的时候, Pod 列表发生了变化, 原来的两个Pod 的状态变成Terminating, 而有出现了两个新的pod:

NAME READY STATUS RESTARTS AGEsise-deploy-67fd84bd5c-fm8v6 1/1 Running 0 5ssise-deploy-67fd84bd5c-svw25 1/1 Running 0 7ssise-deploy-747848cd97-4z6qb 1/1 Terminating 0 3h24msise-deploy-747848cd97-g67pm 1/1 Terminating 0 3h24m

我们现在看到的是两个新的Pod的更新版本1.0以及两个旧的Pod的版本0.9的终止,让我们使用curl在集群中进行验证:

kubectl exec sise-deploy-67fd84bd5c-fm8v6 -t -- curl -s curl -s 127.0.0.1:9876/info

返回结果:

{"host": "127.0.0.1:9876", "version": "1.0", "from": "127.0.0.1"}

可以看到, Pod 已经被更新了, 返回的结果是读取最新的环境变量的值, 对于Deployment 而言, 这种更新就叫做滚动升级.

滚动升级:滚动升级是一种平滑的升级方式,通过逐步替换的策略,保证整体系统的稳定性。

滚动升级

看看滚动升级(Rolling Update)的官方定义:

滚动更新允许通过用新的Pod实例增量更新Pod实例,从而在零停机时间的情况下进行Deployment的更新。

用户期望应用程序始终可用,并且开发人员应每天部署几次新版本的应用程序。 在Kubernetes中,这是通过滚动更新来完成的。 滚动更新允许通过用新的Pod实例增量更新Pod实例,从而在零停机时间的情况下进行Deployment的更新。 新的Pod将在具有可用资源的节点上安排。

当我们在查看我们这个sise-deployment的时候, 我们在Dashboard 上能看到这么一个信息:

可以看到在Resource里面, 有一个RollingUpdate的策略以及条件.

Deployment的回滚

回滚(rollout)是指,当升级Pod的时候如果出现问题,可以使用回滚操作回滚到之前的任一版本.

我们先来看看Deployment 的部署历史:

kubectl rollout history deploy/sise-deploy

结果可以看出,当前有两次部署的历史.

deployment.apps/sise-deploy REVISION  CHANGE-CAUSE1         <none>2         <none>

让我们来把Deployment 回滚到第一个版本:

kubectl rollout undo deploy/sise-deploy --to-revision=1

结果:

deployment.apps/sise-deploy rolled back

在roll back 命令执行期间,我在另外一个命令行查询Pod 状态, 显示出roll back 操作背后Pod 的操作:

可以看到, 新的Pod(名称后缀7rlxp, kzf2q) 已经是运行状态, 而之前的Pod(后缀fm8v6, svw25)正在被销毁.

而当再次查询Pod 状态时, 就只有新的Pod 在运行了:

kubectl get pods --selector 'app=sise'

结果:

NAME READY STATUS RESTARTS AGEsise-deploy-747848cd97-7rlxp 1/1 Running 0 10msise-deploy-747848cd97-kzf2q 1/1 Running 0 10m

下面我们再一次来看看Deployment 的历史:

kubectl rollout history deploy/sise-deploy

结果:

deployment.apps/sise-deploy REVISION  CHANGE-CAUSE2         <none>3         <none>

可以看出, sise-deploy的历史已经有三次了.

我们这次再来调用一下:

kubectl exec sise-deploy-747848cd97-7rlxp -t -- curl -s 127.0.0.1:9876/info

结果:

{"host": "127.0.0.1:9876", "version": "0.9", "from": "127.0.0.1"}

可以看出, 回滚确实起作用了, 返回的结果就是应用的第一个版本的变量值.

操作的部分完成了, 下面来总结和学习Deployment的概念.

Workload 是什么

在介绍正式的Deploymeng 之前, 我们先来看下什么是工作负载,workload, 这个术语, 我们已经提过好多次了, 现在我们来正式看一下.

工作负载(workload), 就是在 Kubernetes 上运行的应用程序。

无论你的负载是单一组件还是由多个一同工作的组件构成,在 Kubernetes 世界,这个负载一定是在一组Pod 中运行。 在 Kubernetes 中,Pod 代表的是集群上处于运行状态的一组容器(container)。

Pod 在Kubernetes中有着明确的生命周期。 例如,一旦一个Pod 在集群中运行,Pod 运行所在的节点出现致命错误时, 所有该节点上的 Pods 都会失败。Kubernetes 将这类失败视为最终状态: 即使该节点后来恢复正常运行,你也需要创建一组新(new)的Pod 来恢复应用。

不过,为了让用户的日子略微好过一些,Kubernetes的用户并不需要直接管理每个 Pod。 相反,可以使用 负载资源(workload resource) 替用户来管理一组 Pod。用这些资源配置控制器(Controller)来确保合适类型的、处于运行状态的 Pod 个数是正确的,与指定的状态相一致。

这其实就是一种控制器模式.

在Kubernetes中, 一个控制器至少追踪一种类型的 Kubernetes 资源。这些 对象有一个代表期望状态的 spec 字段。 该资源的控制器负责确保其当前状态接近期望状态。

Kubernetes 提供若干种内置的工作负载资源, 我们这次把目光放得长一些, 尽管我们暂时只用到了Deployment和Replica Set, 但是可以稍微了解的多一些:

Deployment 和 Replica Set (替换原来的资源 ReplicationController)。 Deployment 很适合用来管理你的集群上的无状态应用,Deployment 中的所有 Pod 都是相互等价的,并且在需要的时候被换掉。StatefulSet 让你能够运行一个或者多个以某种方式跟踪应用状态的 Pods。 例如,如果你的负载需要把数据进行持久化存储,你可以运行一个 StatefulSet,将每个 Pod 与某个 PersistentVolume 对应起来。在 StatefulSet 中, 各个 Pod 内运行的代码可以将数据复制到同一个StatefulSet 中的其它 Pod 中, 以提高整体的服务可靠性。DaemonSet 定义提供节点本地支撑设施的 Pods。这些 Pods 可能对于你的集群的运维是 非常重要的,例如作为网络链接的辅助工具或者作为网络 插件 的一部分等等。每次你向集群中添加一个新节点时,如果该节点与某 DaemonSet 的规约匹配,则控制面会为该 DaemonSet 调度一个 Pod 到该新节点上运行。Job 和 CronJob。 定义了一些一直运行到结束并停止的任务。Job 用来表达的是一次性的任务,而CronJob 会根据其时间规划反复运行。Pod 的生命周期

Pod 遵循一个预定义的生命周期,起始于 Pending 阶段,如果至少 其中有一个主要容器正常启动,则进入 Running,之后取决于 Pod 中是否有容器以 失败状态结束而进入 Succeeded 或者 Failed 阶段。

在 Pod 运行期间,kubelet 能够重启容器以处理一些失效场景。 在 Pod 内部,Kubernetes 跟踪不同容器的状态 并确定使 Pod 重新变得健康所需要采取的动作。

在 Kubernetes API 中,Pod 包含规约部分和实际状态部分。 Pod 对象的状态包含了一组 Pod 状况(Conditions)。 如果应用需要的话,你也可以向其中注入自定义的就绪性信息。

Pod 在其生命周期中只会被调度一次。 一旦 Pod 被调度(分派)到某个节点,Pod 会一直在该节点运行,直到 Pod 停止或者 被终止。

和一个个独立的应用容器一样,Pod 也被认为是相对临时性(而不是长期存在)的实体。 Pod 会被创建、赋予一个唯一的 ID(UID), 并被调度到节点,并在终止(根据重启策略)或删除之前一直运行在该节点。

如果一个节点死掉了,调度到该节点 的 Pod 也被计划在给定超时期限结束后删除。

Pod 自身不具有自愈能力。如果 Pod 被调度到某节点 而该节点之后失效,或者调度操作本身失效,Pod 会被删除;与此类似,Pod 无法在节点资源 耗尽或者节点维护期间继续存活。Kubernetes 使用一种高级抽象,称作 控制器,来管理这些相对而言 可随时丢弃的 Pod 实例。

任何给定的 Pod (由 UID 定义)从不会被“重新调度(rescheduled)”到不同的节点; 相反,这一 Pod 可以被一个新的、几乎完全相同的 Pod 替换掉。 如果需要,新 Pod 名字可以不变,但是其 UID 会不同。

Deployment做什么

一个 Deployment 为 Pods 和 ReplicaSets 提供声明式的更新能力。

我们一般通过定义一个Deployment文件, 来描述 Deployment 中的目标状态,而 Deployment 控制器(Controller) 以受控速率更改实际状态, 使其变为期望状态。你可以定义 Deployment 以创建新的 ReplicaSet,或删除现有 Deployment, 并通过新的 Deployment 收养其资源。

这就是Deployment的能力, 他能做到:

确保Pod数量:它会确保Kubernetes中有指定数量的Pod在运行,如果少于指定数量的Pod,RC就会创建新的,反之这会删除多余的,保证Pod的副本数量不变。确保Pod健康:当Pod不健康,比如运行出错了,总之无法提供正常服务时,RC也会杀死不健康的Pod,重新创建新的。弹性伸缩:在业务高峰或者低峰的时候,可以用过RC来动态的调整Pod数量来提供资源的利用率,当然我们也提到过如果使用HPA这种资源对象的话可以做到自动伸缩。滚动升级:滚动升级是一种平滑的升级方式,通过逐步替换的策略,保证整体系统的稳定性事件和状态查看:可以查看Deployment的升级详细进度和状态回滚:当升级Pod的时候如果出现问题,可以使用回滚操作回滚到之前的任一版本版本记录:每一次对Deployment的操作,都能够保存下来,这也是保证可以回滚到任一版本的基础暂停和启动:对于每一次升级都能够随时暂停和启动回顾

本篇主要学习了Deployment的基本操作,包括:

创建 Deployment 以将 ReplicaSet 上线。 ReplicaSet 在后台创建 Pods。 检查 ReplicaSet 的上线状态,查看其是否成功。更新 Deployment ,声明 Pod 的新状态 。 新的 ReplicaSet 会被创建,Deployment 以受控速率将 Pod 从旧 ReplicaSet 迁移到新 ReplicaSet。 每个新的 ReplicaSet 都会更新 Deployment 的修订版本。如果 Deployment 的当前状态不稳定,回滚到较早的 Deployment 版本。 每次回滚都会更新 Deployment 的修订版本。

涉及的操作:

kubectl get deploy

查看Deployment的情况,其中deploy 是缩写

kubectl get rs

查看Replica Set的情况, 其中rs 缩写

kubectl api-resources

查看kubectl 操作的所有的资源名称

kubectl rollout history deploy/sise-deploy

查看deployment的历史版本信息

kubectl rollout undo deploy/sise-deploy --to-revision=1

Deployment 回滚

0 阅读:0

查理谈科技

简介:感谢大家的关注