【公开课】应用编排和管理核心原理|学习笔记

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 快速学习【公开课】应用编排和管理核心原理。

开发者学堂课程【应用编排与管理核心原理:【公开课】应用编排和管理核心原理】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/828/detail/13947


【公开课】应用编排和管理核心原理

 

内容:

一、课程目标

二、资源元信息

三、操作演示

四、控制器模式

五、控制器模式总结

 

一、课程目标

学习 K8s 的应用编排和管理核心原理,讲解分为四个部分和课后习题,首先讲解 K8s 的重要资源元信息,第二部分是利用阿里云服务器演示如何查看和修改 K8s 的资源的元数据,第三部分是分析控制器模式,第四部分是对控制器模式的总结。

 

二、资源元信息

1. Kubernetes 资源对象的组成

(1)Spec 部分:用于描述期望的状态

(2)Status 部分:用于描述观测到的状态

以上都是之前提及的。

(3)元数据Metadata

①用于识别资源的标签 Labels

②用于描述资源的注解 Annotations

③用于描述资源之间相互关系 OwnerReference

这些元数据在 K8s 运行中有非常重要的作用。

2.Labels

1)标签 Labels 是一种标识型的 Key:Value 元数据,它也是最重要的元数据。

以下都是常用的资源标签

environment:production

release:stable

app.kubernetes.io/version:5.7.21

failure-domain.beta.kubernetes.io/region: cn-hangzhou

可以看到,前三个标签都标明了对应应用的环境,版本等,同时从应用名字的标签可以看到,标签的名字可以包括域名的前缀,用于描述打标签的系统和工具对标签的重置。而最后的标签打在了与前面三个不同的对象上,同时在域名前增加了版本的标识 beta 字符串。

2)Labels 作用

①用于筛选资源

②唯一的组合资源的方法

3)可以使用 selector SQL 查询语句中的相关资源

类似于SQL ‘select*where….’

(4)Selector

①最常见的 Selector 是相等型 Selector 如:Tie=front Env=dev ,举个例子,假设系统主要有四个 Pod,每个 Pod 都有标记系统环境和层级的标签,通过 Tie:front 这个可以匹配左边的 pod ,相等型的 Selector 还可以包括多个相等条件,且多个相等条件之间是逻辑与的关系,在刚才的例子中,通过Tie=front Env=dev  Selector 可以筛选出所有的 Tie:front 而且还可以筛选出 Env:prod

②第二种 Selector 是集合型 Selector 如:Env in (test,gray) ,在例子中 Selector 筛选的所有环境是 test 或者 gray Pod。除 in 的集合操作外,还有其他集合操作如 notin 操作,比如:tie notin (front,back),将筛选所有的 tie  不是 front 且不是 back Pod,另外也可以根据是否存在某 Label 来筛选,如:Selector release ,筛选所有带 release 标签的 Pod。

集合型和相等型的 Selector 之间可以用逗号连接,同样表示逻辑与的关系。

4. Annotations

(1)Key: Value

常见的 Annotations 有:

①存储了阿里云负载均衡器的证书ID

service.beta.kubernetes.io/alicloud-loadbalancer-cert-id:your-cert-id

可以看到,annotations 同样具有域名的前缀,标注中也可以包含版本信息。

②存储了nginx 接入层的配置信息:

nginx.ingress.kubernetes.io/service-weight: “new-nginx:20,old-nginx:60"

可以看到,annotations 包括逗号等无法在 Labels 中出现的特殊字符。

③在 kubectl apply 命令操作后的资源可以看到:

kubectl.kubernetes.io/last-applied-configuration:

Annotations 的值是一个结构化的数据,实际上是一个 json 串,标记了上一次 kubectl 操作的资源的 json 的描述。

(2)作用:

①用于存储资源的非标识性信息

②可以扩展资源的 spec/status 描述

(3)特点:

①一般比 label 更大

②可以包含特殊字符

③可以结构化也可以非结构化

5. OwnerReference

(1)“所以者”即集合类资源,如:Pod 的集合中的replicaset,statefulset

(2)集合类资源的控制器会创建对应的归属资源,如:Replicaset 控制器在操作中会创建 Pod,被创建的 Pod OwnerReference 就指向了创建 Pod 的 replicaset。

如图:

image.png

(3)作用

①使用户方便反向查找一个创建资源的对象

②用于实现进行级联删除的效果

  

三、操作演示

通过 kubectl 命令去连接 ACK 中已经创建好的一个 k8s 集群,然后展示如何查看和修改 k8s 对象里的元数据,主要是 Pod 的标签、注解和对应的 OwnerReference

1.创建 port

首先查看集群现在的配置情况,如图:

image.png

可以看到,集群中最开始是没有 port 的。

然后用事先准备好的一个 Pod 的 yaml 文件,用它来进行创建一个 Pod ,如图:

image.png

2.查看 pod 中的标签

然后用 show-labels 的方式查看 Pod 打的标签,如图:

image.png

可以看到,两个 Pod 都打上了一个部署环境和层级的标签,然后还可以通过另外的方式查看具体一个资源的信息,如图:

image.png

首先查看 nginx1 第一个 Pod 的一个信息,再利用 -o 方式,用 yaml 文件输出,如图:

image.png

可以看到,第一个 Pod 元数据里包括了一个 labels 的字段,里面有两个 label。 

3.如何修改 port 中已有的 labels

如给 labels 加上标签,把部署环境从开发环境换成测试环境,该如何操作?

如图:

image.png

指定 Pod 名字,在环境上加一个它的一个值 test ,是无法成功的。

image.png

可以看到,页面显示 label 已经有值,如果想覆盖这个值需要额外加上一个覆盖选项 overwrite 

加上覆盖选项后,如图:

image.png

观察 labels 的设置情况,可以看到,nginx1 已经加上了一个部署环境 test 的标签。

同样的,如果想去掉 Pod 中的一个标签也是一样的操作,但是 env 后不是加上=,而是只加上 labels 名字,后面不加=改成使用-表示去除。

如图:

image.png

可以看到,这个labels 已经去标成功,然后看配置的 label 值,能发现 nginx1 的一个 Pod 少了一个 Tie=front 标签,并且 port 少了一个 Tie=front 标签。

4.如何用 labels selector 进行匹配

1)使用相等型 labels selector 

如图:

image.png

有了这两个 Pod 标签之后,可以用 labels selector 来进行匹配,首先,labels selector 是通过-l这个选项进行指定的,指定的时候,先试一下用相等型的一个 label 来筛选,这里指定的是部署环境等于测试环境的一个 Pod 

如图:

image.png

zimage.png

假设有多个相等的条件需要指定,实际上这是一个逻辑与的关系,如果 env 等于 dev ,此时一个 Pod 都无法拿到。然后再假设 env=dev ,但若 tie=front,此时可以匹配到第二个 Pod,也就是 nginx2

(2)使用集合型 labels selector

如图:

image.png

可以看到,如果这次还是想匹配出所有部署环境是 test 或者是 dev 的一个Pod,需要在 show-labels 后面加上引号,然后在括号里指定所有部署环境的一个集合。这样可以把两个创建的 Pod 都筛选出来。

5.如何对 Pod 增加注解

如图

image.png

可以看到,增加注解和前面的打标是一样的操作,但是需要把 label 命令改成 annotate 命令,然后一样指定类型和对应的名字。但是后面不是加上 label 的k:v 而是加上 annotate 的 k:v。这里可以指定一个任意的字符串,比如加上空格或者逗号。

然后,再看 Pod 的一些元数据,如图:

image.png

可以看到,这个 Pod 的一些元数据里面的 annotation ,还有一个 my-annotate 这个 Annotations。

image.png

然后还能看到,这里其实有一个 kubectl apply 的时候,kubectl 工具增加了一个 annotation ,这也是一个 json 串,里面也有很多特殊字符。

6.OwnerReference

下面演示 Pod OwnerReference 是怎么出来的,原来的 Pod 都是直接通过创建 Pod 这个资源方式来创建的,这次可以换另一种方式来进行创建:通过创建一个 Replicaset 对象来创建 Pod 

如图:

image.png

首先创建一个 Replicaset 对象,然后可以具体查看这个 Replicaset 对象,如图:

image.png

需要关注的是,这个 Replicaset 里面的 spec 里提到会创建两个 Pod ,然后 selector 通过匹配部署环境是 product 生产环境的这个标签来进行匹配。然后在看一下现在集群中 Pod 情况,如图:

image.png

image.png

可以看到,集群中多了两个 Pod ,仔细查看这两个 Pod ,会发现 Replicaset 创建出来的 Pod 有一个特点,即它带有 OwnerReference,然后 OwnerReference 里面指向了是一个 replicasets 类型,名字就叫做 nginx-replicasets。

 

四、控制器模式

1.控制循环

控制器模式最核心的概念就是控制循环的概念,在控制循环中,包括了控制器、被控制的系统以及能够观测系统的传感器这三个逻辑组件,外界通过修改资源的 spec 来机制资源,控制器比较资源的 spec、status ,从而计算一个 diff,diff 最终会用于决定系统执行什么控制操作,控制操作会使系统产生新的输出,并被传感器以资源 status 的形式上报,控制器的各个组件都将会独立自主的运行,不断的使系统向 spec 表示终态(status->spec)趋近。

2.sensor

(1)Reflector 和 Informer

如图:

image.png

可以看到,控制循环中逻辑的成分主要由 Reflector、Informer、Indexer 三个组件构成

Reflector

Reflector 通过 List Watch  K8s server 来获取资源数据,List 用于 Controller 重启以及 Watch 中断的情况下进行系统资源的全量更新;而 Watch 则在多次 List 之间进行增量的资源更新。Reflector 在获取新的资源数据后,会在一个 Delta 队列中塞入一个包括资源对象信息本身以及资源对象事件类型的 Delta 记录,Delta 队列中可以保证同一个对象在队列中仅有一条记录,从而避免  Reflector 重新 List 和 Watch 的时候产生重复的记录。

②Informer

Informer 组件不断地从 Delta 队列中弹出 delta 记录,一方面把资源事件交给资源的回调函数,同时又把资源对象交给 indexer,让 indexer 把资源记录在一个缓存中,缓存在默认设置下是用资源的命名空间来做索引的,并且可以被 Controller  Manager或多个 Controller 所共享。

③控制模式中的控制器

控制循环中的控制器组件主要由事件处理函数以及 worker 组成,事件处理函数之间会相互关注资源的新增、更新、删除的事件,并根据控制器的逻辑去决定是否需要处理。对需要处理的事件,会把事件关联资源的命名空间以及名字塞入一个工作队列中,并且由后续的 worker 池中的一个 Worker 来处理,工作队列会对存储的对象进行去重,从而避免多个 Woker 处理同一个资源的情况。Worker 在处理资源对象时,一般需要用资源的名字来重新获得最新的资源数据,用来创建或者更新资源对象,或者调用其他的外部服务,Worker 如果处理失败的时候,一般情况下会把资源的名字重新加入到工作队列中,从而方便之后进行重试。

3.控制循环例子-扩容

(1)控制循环的工作原理:Replicaset 是一个用于描述无状态应用的扩缩容行为的资源,在 Replicaset Controller 通过监听 Replicaset 资源来维持应用希望的资源数量,Replicaset 中,通过 selector 来匹配所有关联的 Pod,在这里,考虑 Replicaset 中 rsa 的 Replicaset ,如图:

image.png

replicas 从2改成3的场景。

首先,Reflector 会 watch 到 ReplicaSet 和 Pod 两种资源的变化。发现 ReplicaSet 发生变化后,在 delta 队列中塞入了对象是 rsA ,而且类型是更新的记录。同时 informer 一方面把新的 ReplicaSet 更新到缓存中,并与 Namespace nsA 作为索引。另外一方面,调用 Update 的回调函数,ReplicaSet 控制器发现 ReplicaSet 发生变化后会把字符串的 nsA/rsA 字符串塞入到工作队列中,工作队列后的一个 Worker 从工作队列中取到了 nsA/rsA 这个字符串的 key ,并且从缓存中取到了最新的ReplicaSet 数据。Worker 通过比较 ReplicaSet 中 spec 和 status 里的数值,发现需要对这个 ReplicaSet 进行扩容,因此 ReplicaSet 的 Worker 创建了一个 Pod ,这个 pod 中的Ownereference 取向了 ReplicaSet rsA。

详情可见下图:

image.png

然后 Reflector Watch 到的 Pod 新增事件,在 delta 队列中额外加入了 Add 类型的 deta 记录,一方面把新的 Pod 记录通过 Indexer 存储到了缓存中,另一方面调用了 ReplicaSet 控制器的 Add 回调函数,Add 回调函数通过检查 podownerReferences 找到了对应的 ReplicaSet,并把包括 ReplicaSet 命名空间和字符串塞入到了工作队列中。ReplicaSet 的 Noker 在得到新的工作项之后,从缓存中取到了新的 ReplicaSet 记录,并得到了其所有创建的 Pod,因为 ReplicaSet 的状态不是最新的,也就是所有创建 Pod 的数量不是最新的。因此在此时 ReplicaSet spec 和 status 达成一致。

详情可见下图:

image.png

 

五、控制器模式总结

Kubernetes 控制器的模式依赖声明式的 API ,另外一种常见的 API 还有命令式的 API Kubernetes 采用的是声明式的 API 而不是命令式的 API 来设计整个控制器。

1.比较两种 API 在交互行为上的差别

在生活中,常见的命令式的交互方式就是家长和孩子交流的方式。因为孩子欠缺目标意识,无法理解家长期望,家长往往通过命令,教孩子一些明确的动作,比如说:吃饭、睡觉类似的命令。容器编排体系中,命令式AP就是通过向系统发出明确的操作来执行的。而常见的声明式 API 就是老板对自己员工的交流方式。老板一般不会给自己的员工下很明确的决定,实际上可能老板对于要执行操作的事情本身,还不如员工清楚。因此,老板通过给员工设置可量化的业务目标的方式,来发挥员工白身的主观能动性。比如说:老板要求某个产品的市场占有率能达到80%,而不会指出要达到这个市场占有率,要做的具体操作细节。类似的,在容器编排体系中,可以指定一个实例的应用副本数保持在3个,而不是明确的说需要通过扩容或者删除一个 Pod 来保证副本数保持在3个。

2.两种 API 方式的问题

(1)命令式 API

命令式 API 存在的最大问题是错误处理。在大规模的分布系统中,错误是无处不在的,一旦发布的命令没有响应,主要通过反复重试的方式来恢复错误,然而盲目的重试可能会带来更大的问题,假设实际上后台的命令完成了,重试会导致多出一个重试命令的操作,因此为了避免重试带来的问题,系统往往会在执行命令前记录下需要执行的命令,在重启的情况下重做待执行的命令,并充分考虑多个命令执行的先后顺序、覆盖关系等等复杂的逻辑情况。实际上许多命令式 API 交互的后台往往还会做巡检的系统,用于修正命令处理超时、重试等异常场景造成数据不一致的问题,然而,由于巡检的逻辑和日常操作的逻辑不同,往往在测试上覆盖不够,在错误处理上不够严谨,具有很大的操作风险,因此巡检系统往往都是由人工触发。最后,命令式 API 在处理在多并发访问上也很容易出现问题,假设有多方并发对资源请求操作,在操作中又出现了错误需要重试,哪个操作出现错误是很难判断的,因此系统往往会在操作前进行加锁,但是加锁会降低整个系统操作的效率。

(2)声明式 API

相比较 命令式 API ,声明式 API 可天然的记录系统现在和最终的状态,不需要额外记录数据,而且状态的幂等操作可在任意时刻反复操作,在声明式 API 系统运行的操作里,正常的操作实际上就是对资源状态的巡检,不需要额外开发巡检系统,系统的运行逻辑也可以在日常运行中得到锤炼和测试,可以保证操作的稳定性。最后,由于资源的最终状态是明确的,因此可以合并多次资源的修改,可以不需要进行加锁等操作。

3.控制器模式总结

如图:

image.png

控制器模式是由声明式的 API 即由 K8S 资源对象的修改来驱动的,在 K8S 资源后是对关注该资源的控制器,然后由控制器异步地控制系统向设置的终态趋近,这些控制器是自主运行的,这使系统的自动化和无人值守化成为可能,由于 K8S 资源和控制器都是可以自定义的,因此方便扩展控制器模式,特别的,对于有状态应用,往往会通过自定义资源和控制器的方式来自动化运维操作也就是 operator 的场景。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
3月前
|
Prometheus 监控 Cloud Native
|
存储 消息中间件 人工智能
阿里是如何使用分布式架构的?阿里内部学习手册分享
为什么要使用分布式架构?分布式架构解决了互联网应用的两大难题:高并发和高可用。高并发指服务器并发处理客户端请求的数量大,而高可用指后端服务能始终处于可用状态。
|
6月前
管理入门到管理进阶需要什么
管理入门到管理进阶需要什么
43 0
|
6月前
|
存储 数据采集 运维
构建高效日志管理系统:阿里云产品实践与技术解析
日志管理对于系统运维和故障排查至关重要。本文将详细介绍如何利用阿里云相关产品搭建一个高效、可扩展的日志管理系统。我们将使用Log Service、Elasticsearch、DataHub等阿里云产品,通过代码示例和详细说明,带你一步步完成整个流程。
346 0
|
Kubernetes 负载均衡 网络协议
【云原生|K8s系列第1篇】:K8s的基础概念、组件架构及实战安装
首先,K8s并不是一个传统意义上的 PaaS平台即服务的工具,它充分给使用者提供了很多很多选择的空间。
【云原生|K8s系列第1篇】:K8s的基础概念、组件架构及实战安装
|
消息中间件 监控 Cloud Native
阿里云云原生每月动态 | 聚焦实战,面向开发者的系列课程全新上线
《阿里云云原生每月动态》,从趋势热点、产品新功能、服务客户、开源与开发者动态等方面,为企业提供数字化的路径与指南。
阿里云云原生每月动态 | 聚焦实战,面向开发者的系列课程全新上线
|
SQL JSON Kubernetes
KubeVela 项目和能力简介 | 学习笔记
快速学习 KubeVela 项目和能力简介
KubeVela 项目和能力简介 | 学习笔记
|
调度 数据库
任务调度 Quartzh 框架企业级实战案例
任务调度 Quartzh 框架企业级实战案例
152 0
|
传感器 存储 SQL
应用编排与管理:核心原理|学习笔记
快速学习应用编排与管理:核心原理
117 0
应用编排与管理:核心原理|学习笔记
|
前端开发 架构师 Serverless
人人都是Serverless架构师之传统内容管理系统改造实战一[开篇]
内容管理系统是很常见的一种web应用场景,可以用到个人独立站,企业官网展示等场景,具有很高的实用价值,一个标准的内容管理系统主要由三个部分组成 主站展示部分、后台管理系统、API接口服务,本系列文章会以一个已有内容管理系统的Serverless架构重构展开,介绍改造的基本思路,改造细节,以及性能优化业务可观测设计等。涉及大家关心的Serverless生产遇到的一些问题,比如数据库、日志、动静态分离、调试、维护、灰度方案等。最真实的展现Serverless架构的实施落地细节。 本篇章作为系列文章的开篇,大致讲解一下将传统前端应用重构成Serverless架构的架构设计方案,工程改造思路,以及部署
285 0
人人都是Serverless架构师之传统内容管理系统改造实战一[开篇]