读《周志明的软件架构课》--学习笔记和感想随笔

主要记录对周老师的《周志明的软件架构课》的学习笔记,本篇章是对课程不可变基础设施部分的学习,从虚拟化的技术理解容器技术的产生和发展,从部署运维角度理解应用的封装,从网络虚拟化理解容器网络,从扩展的角度理解K8s的存储设计,从解耦的角度理解服务网格。从周老师的课程中可以以一种由浅入深的方式来探寻云原生技术的渊源、发展及使用。

另外对架构部分和分布式部分的学习及总结在之前博客中:
架构设计方法论-思维导图梳理
分布式系统方法论–思维导图梳理

45 | 模块导学:从微服务到云原生

不可变基础设施
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。
这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。
虚拟化的目标与类型
容器是云计算、微服务等诸多软件业界核心技术的共同基石。容器的首要目标是让软件分发部署的过程,从传统的发布安装包、靠人工部署,转变为直接发布已经部署好的、包含整套运行环境的虚拟化镜像。
三方面的兼容性
- ISA 兼容:目标机器指令集兼容性,比如 ARM 架构的计算机无法直接运行面向 x86 架构编译的程序。
-指令集架构(Instruction Set Architecture,ISA)是计算机体系结构中与程序设计有关的部分,包含了基本数据类型、指令集、寄存器、寻址模式、存储体系、中断、异常处理以及外部 I/O。指令集架构包含一系列的 Opcode 操作码(即通常所说的机器语言),以及由特定处理器执行的基本命令。
- ABI 兼容:目标系统或者依赖库的二进制兼容性,比如 Windows 系统环境中无法直接运行 Linux 的程序,又比如 DirectX 12 的游戏无法运行在 DirectX 9 之上。
- 应用二进制接口(Application Binary Interface,ABI)是应用程序与操作系统之间或其他依赖库之间的低级接口。ABI 涵盖了各种底层细节,如数据类型的宽度大小、对象的布局、接口调用约定等等。ABI 不同于应用程序接口(Application Programming Interface,API),API 定义的是源代码和库之间的接口,因此同样的代码可以在支持这个 API 的任何系统中编译,而 ABI 允许编译好的目标代码在使用兼容 ABI 的系统中无需改动就能直接运行。
- 环境兼容:目标环境的兼容性,比如没有正确设置的配置文件、环境变量、注册中心、数据库地址、文件系统的权限等等,当任何一个环境因素出现错误,都会让你的程序无法正常运行。
五类虚拟化技术
- 指令集虚拟化
- 即通过软件来模拟不同 ISA 架构的处理器工作过程,它会把虚拟机发出的指令转换为符合本机 ISA 的指令,代表为QEMU和Bochs。
- 指令集虚拟化就是仿真,它提供了几乎完全不受局限的兼容性,甚至能做到直接在 Web 浏览器上运行完整操作系统这种令人惊讶的效果。但是,由于每条指令都要由软件来转换和模拟,它也是性能损失最大的虚拟化技术。
- 硬件抽象层虚拟化
- 即以软件或者直接通过硬件来模拟处理器、芯片组、内存、磁盘控制器、显卡等设备的工作过程。
- 操作系统层虚拟化
- 操作系统层虚拟化则不会提供真实的操作系统,而是会采用隔离手段,使得不同进程拥有独立的系统资源和资源配额,这样看起来它好像是独享了整个操作系统一般,但其实系统的内核仍然是被不同进程所共享的。
- 操作系统层虚拟化的另一个名字 就是 容器化 ,容器化牺牲了一定的隔离性与兼容性,换来的是比前两种虚拟化更高的启动速度、运行性能和更低的执行负担
- 运行库虚拟化
- 与操作系统虚拟化采用隔离手段来模拟系统不同,运行库虚拟化选择使用软件翻译的方法来模拟系统,它是以一个独立进程来代替操作系统内核,来提供目标软件运行所需的全部能力。
- 语言层虚拟化
由虚拟机将高级语言生成的中间代码,转换为目标机器可以直接执行的指令,代表为Java的JVM和.NET 的CLR 。

46 | 容器的崛起(上):文件、访问、资源的隔离

隔离文件:chroot
chroot \ jailbreak \ pivot_root
隔离访问:namespaces
Linux的名称空间是一种有内核直接提供的全局资源封装,它是内核针对进程设计的访问隔离机制。
Mount \ UTS \ IPC \ PID \ Network | User | Cgroup | Time
隔离资源:cgroups
如果要让一台物理计算机中的各个进程看起来像独享整台虚拟计算机的话,不仅要隔离各自进程的访问操作,还必须能独立控制分配给各个进程的资源使用配额。不然的话,一个进程发生了内存溢出或者占满了处理器,其他进程就莫名其妙地被牵连挂起,这样肯定算不上是完美的隔离。
直接由内核提供的功能,用于隔离或者说分配并限制某个进程组能够使用的资源配额
biko | cpu | cpuaact | cpuset | devices | freezer | memory | net_cls | net_prio | hugetlb | perf_event

47 | 容器的崛起(下):系统、应用、集群的封装

封装系统: LXC
一种封装系统的轻量级虚拟机
封装应用:Docker
源于LXC 、AUFS , 简单模拟Bocker ;
跨机器的绿色部署
以应用为中心的封装
自动构建
多版本支持
组件重用
共享
工具生态

子系统:
Docker Client \ Docker Daemon \ Docker Registry \ Docker Container | 
Graph \Driver \ libcontainer 
OCI : 运行时标准runtime-spec 容器镜像标准image-spec 镜像分发标准distribution-spec
	libcontainer -> runC 项目  、 Docker Daemon -> containerd 项目

封装集群:Kubernetes
如果说以 Docker 为代表的容器引擎,是把软件的发布流程从分发二进制安装包,转变为了直接分发虚拟化后的整个运行环境,让应用得以实现跨机器的绿色部署;
那以 Kubernetes 为代表的容器编排框架,就是把大型软件系统运行所依赖的集群环境也进行了虚拟化,让集群得以实现跨数据中心的绿色部署,并能够根据实际情况自动扩缩。
k8s与容器引擎的调用关系
Kubernetes Master → kubelet → DockerManager → Docker Engine → containerd → runC
1.5变化后:
Kubernetes Master → kubelet → KubeGenericRuntimeManager → DockerShim → Docker Engine → containerd → runC
1.10 版本后
Kubernetes Master → kubelet → KubeGenericRuntimeManager → containerd → runC

48 | 以容器构建系统(上):隔离与协作

一个容器封装一个单进程应用 
分布式系统里应用需要多个进程共同协作,通过集群的形式对外提供服务,那么以虚拟化方法实现这个目标的过程,就称为容器编排

构建容器编排系统时都会遇到什么问题?
- 场景一 : 假设你现在有两个应用,其中一个是Nginx ,另一个是为该Nginx 收集日志的Filebeat , 你希望将他们封装为容器镜像,以便日后分发。
- 场景二: 假设你现在有两个Docker 镜像,其中一个封装了HTTP服务,为便于称呼,叫它NGINX容器,另一个封装了日志收集服务,叫它Filebeat容器。现在你要求Filebeat容器能收集Nginx容器产生的日志信息。 confd 共享IPC名称空间 --net 共享网络名称空间
- 如果容器与进程在概念上对应起来,那容器编排的第一个扩展点,就是要找到容器领域中与进程组想对应的概念,这是实现容器从隔离到协作的第一步。在K8s 的设计里,这个对应物叫做Pod 。
Pod的含义与指责
扮演容器组的角色,满足容器共享名称空间的需求,是Pod两大最基本的职责之一。
UTS名称空间 主机名和域名 , 网络名称空间 、 IPC名称空间 、 时间名称空间
- 场景三:假设你现在有Filebeat \ Nginx 两个Docker镜像 ,在一个具有多个节点的集群环境下,要求每次调度都必须让Filebeat和Nginx 容器运行在同一个节点上。
实现原子性调度
Pod是隔离与调度的基本单位
计算资源:
容器 Container
生产任务 Pod
节点 Node
集群 Cluster
集群联邦 Federation

49 | 以容器构建系统(下):韧性与弹性

控制器设计模式
编排系统如何快速调整出错的服务?
- 场景四: 假设有个由数十个Node、数百个Pod、近千个Container所组成的分布式系统,作为管理员,你想要避免该系统因为外部流量压力、代码缺陷、软件更新、硬件升级、资源分配等各种原因而出现中断的状况,那么你希望编排系统能为你提供何种支持?
控制回路:
声明式API
额外知识:Kubernates 的资源对象与控制器目前,Kubernetes 已内置支持相当多的资源对象,并且还可以使用CRD(Custom Resource Definition)来自定义扩充,你可以使用 kubectl api-resources 来查看它们。下面我根据用途分类,给你列举了一些常见的资源:
- 用于描述如何创建、销毁、更新、扩缩 Pod,包括:Autoscaling(HPA)、CronJob、DaemonSet、Deployment、Job、Pod、ReplicaSet、StatefulSet
- 用于配置信息的设置与更新,包括:ConfigMap、Secret
- 用于持久性地存储文件或者 Pod 之间的文件共享,包括:Volume、LocalVolume、PersistentVolume、PersistentVolumeClaim、StorageClass
- 用于维护网络通信和服务访问的安全,包括:SecurityContext、ServiceAccount、Endpoint、NetworkPolicy
- 用于定义服务与访问,包括:Ingress、Service、EndpointSlice
- 用于划分虚拟集群、节点和资源配额,包括:Namespace、Node、ResourceQuota
这些资源在控制器管理框架中,一般都会有相应的控制器来管理,这里我也列举了一些常见的控制器,按照它们的启动情况进行了分类,如下:
- 必须启用的控制器:EndpointController、ReplicationController、PodGCController、ResourceQuotaController、NamespaceController、ServiceAccountController、GarbageCollectorController、DaemonSetController、JobController、DeploymentController、ReplicaSetController、HPAController、DisruptionController、StatefulSetController、CronJobController、CSRSigningController、CSRApprovingController、TTLController
- 默认启用的可选控制器,可通过选项禁止:TokenController、NodeController、ServiceController、RouteController、PVBinderController、AttachDetachController
- 默认禁止的可选控制器,可通过选项启用:BootstrapSignerController、TokenCleanerController
实际状态有可能发生变化的资源对象,通常会由对应的控制器进行追踪,每个控制器至少会追踪一种类型的资源。 统一的控制器管理框架 kube-controller-manager、 统一的指标监视器 kube-apiserver
Kubernetes 控制器模式的工作原理
- 场景五 : 通过服务编排,我们让任何分布式系统自动实现以下三种通用的能力,
Pod出现故障时,能够自动恢复,不中断服务;
Pod更新程序时,能够滚动更新,不中断服务;
Pod遇到压力时,能够水平扩展,不中断服务。

50 | 应用为中心的封装(上):Kustomize与Helm

Kustomize :
用配置文件来配置文件 基于YAML的模版
根据环境来生成不同的部署配置
Helm与Chart
如果说Kubernetes 是云原生操作系统的话,那Helm就要成为这个操作系统上面的应用商店与包管理工具。
Chart格式 、 Repository 应用仓库 、 多版本-Release

WordPress
 ├── templates
 │     ├── NOTES.txt
 │     ├── deployment.yaml
 │     ├── externaldb-secrets.yaml
 │     └── 版面原因省略其他资源文件
 │     └── ingress.yaml
 └── Chart.yaml
 └── requirements.yaml
 └── values.yaml
 
Chart.yaml 给出了应用自身的详细信息(名称、版本、许可证、自述、说明、图标,等等),requirements.yaml 给出了应用的依赖关系,依赖项指向的是另一个应用的坐标(名称、版本、Repository 地址),values.yaml 给出了所有可配置项目的预定义值。
由于 Chart 封装了足够丰富的信息,所以 Helm 除了支持命令行操作外,也能很容易地根据这些信息自动生成图形化的应用安装、参数设置界面。
Repository 仓库。它主要是用于实现 Chart 的搜索与下载服务,Helm 社区维护了公开的 Stable 和 Incubator 的中央仓库(界面如下图所示),也支持其他人或组织搭建私有仓库和公共仓库,并能够通过 Hub 服务,把不同个人或组织搭建的公共仓库聚合起来,形成更大型的分布式应用仓库,这也有利于 Chart 的查找与共享。

整体来说,Helm 提供了应用全生命周期、版本、依赖项的管理能力,同时,Helm 还支持额外的扩展插件,能够加入 CI/CD 或者其他方面的辅助功能
Helm 对于有状态服务,无法很好的管理有状态的额依赖关系

51 | 应用为中心的封装(下):Operator与OAM

Operator
与 Kustomize 和 Helm 不同的是,Operator不应当被称作是一种工具或者系统,它应该算是一种封装、部署和管理 Kubernetes 应用的方法,尤其是针对最复杂的有状态应用去封装运维能力的解决方案 ,
Operator 是通过 Kubernetes 1.7 开始支持的自定义资源(Custom Resource Definitions,CRD,此前曾经以 TPR,即 Third Party Resource 的形式提供过类似的能力),把应用封装为另一种更高层次的资源,再把 Kubernetes 的控制器模式从面向内置资源,扩展到了面向所有自定义资源,以此来完成对复杂应用的管理。
有状态应用会对某些外部资源有绑定性的直接依赖
StatefulSet 管理Pod具备的额外特性:
Pod会按顺序创建和按顺序销毁
Pod具有稳定的网络名称
Pod具有稳定的持久存储
Operator 则是要求开发者自己实现一个专门针对该自定义资源的控制器,在控制器中维护自定义资源的期望状态。
OAM
Components
Workload : 六种类型
Traits : 运维特征
Application Scopes : 应用边界
Application Configuration : 应用配置

解耦开发运维
- 开发人员负责管理 Component;
- 运维人员将 Component 组合并绑定 Trait,把它变成 Application Configuration;
- 平台人员或基础设施提供方负责提供 OAM 的解释能力,将这些自定义资源映射到实际的基础设施。

52 | Linux网络虚拟化(上):信息是如何通过网络传输被另一个程序接收到的?

Linux系统下的网络通信模型
Socket 、 TCP/UDP 、 IP 、 Device 、 Driver
层层封包 加入协议头 , 层层解包 ,提取协议体
干预网络通信的Netfilter 框架
PREROUTING 、INPUT 、FORWORD 、OUTPUT、POSTROUTING
Iptables :
raw mangle nat(source) \ nat(destination) \ filter \ security

53 | Linux网络虚拟化(下):Docker所提供的容器通讯方案有哪些?

虚拟化网络设备
网卡 tun/tap 、veth
交换机 Linux Bridge
网络 VxLan
副本网卡 MACVLAN
容器间通信
桥接模式
主机模式
空置模式
内容需要再细读

54 | 容器网络与生态:与CNM竞争过后的CNI下的网络插件生态

CNM 与CNI
管理网络创建与删除
管理IP地址分配与回收
要符合IPv4的网段规则
必须考虑到回收的问题
还必须要关注时效性
CNM到CNI
在 CNM 和 CNI 提出以前的早期版本里,Kubernetes 会使用 Docker 的空置网络模式(–network=none)来创建 Pause 容器,然后通过内部的 kubenet 来创建网络设施,再让 Pod 中的其他容器加入到 Pause 容器的名称空间中,共享这些网络设施。
kubenet是 kubelet 内置的一个非常简单的网络,它是采用网桥来解决 Pod 间通信。
网络插件生态
overlay 模式 : Flannel-UDP Flannel-VXLAN
路由模式
underlay 模式 MACVLAN

55 | 谈谈Kubernetes的存储设计理念

Kubernetes的存储设计考量
Mount 和 Volume
Static Provisioning
Dynamic Provisioning

56 | Kubernetes存储扩展架构:一个真实的存储系统如何接入或移除新存储设备?

Kubernetes存储架构
决定应准备何种存储 Provision
将准备好的存储附加到系统中 Attach
将附加好的存储挂载到系统中 Mount
PV控制器 (PersistentVolume Controller )
AD控制器 ( Attach \ Detach Controller )
Volume 管理器 ( Volume Manager )
FlexVolume 与 CSI

57 | Kubernetes存储生态系统:几种有代表性的CSI存储插件的实现

块存储 readwriteonce
文件存储 posix
对象存储 分布式 大数据量 kv
选择合适的存储

58 | Kubernetes的资源模型与调度器设计

资源模型
服务质量与优先级
服务质量等级
优先级
驱逐机制
默认调度器

59 | 透明通讯的涅槃(上):通讯的成本

通信的成本
1、将通信的非功能性需求视作业务需求的一部分,由程序员来保障通信的可靠性
2、将代码中的通信功能抽离重构成公共组件库,通信的可靠性由专业的平台程序员来保障
3、将负责通信的公共组件库分离到进程之外,程序间通过网络代理来交互,通信的可靠性由专门的网络代理提供商来保障
4、将网络代理以边车的形式注入到应用容器,自动劫持应用的网络流量,让通信的可靠性由专门的通信基础设施来保障。
对流量的劫持是强制的, 对应用是透明的
5、将边车代理统一管控起来实现安全、可控、可观测的通信,将数据平面与控制平面分离开来,实现通用、透明的通信,这项工作就由专门的服务网格框架来保障。

60 | 透明通讯的涅槃(下):控制平面与数据平面

数据平面
代理注入
流量劫持
可靠通信
控制平面

61 | 服务网格与生态:聊聊服务网格的两项标准规范

服务网络接口 ( Service Mesh Interface, SMI )
流量规范
流量拆分
流量度量
流量访问控制
通用数据平面 API ( Universal Data Plane API , UDPA )
服务网格生态

参考资料:

1、《周志明的软件架构课》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值