2020-03
今天,我们将加快进度,来对Provisioning这一层的项目做一下概览。Provisioning层是一种工具性质的项目,能一定程度上提升Kubernetes的综合能力,尤其是镜像管理和安全性。
KubeEdge在近几年非常火,贴合边缘计算这个概念。
众所周知,由于Kubernetes是一个以master为核心的调度系统,许多核心能力都依赖master节点,会导致边端能力的受限。KubeEdge就是以这个为切入点。
目前落地KubeEdge的公司主要就是以华为为代表,其余大厂并没有加入到这个阵营。我之前的公司也引入过KubeEdge,但整体效果不佳。
在引入KubeEdge前,我们需要思考一个问题:边缘计算的系统一定要结合Kubernetes吗?
Harbor是云原生的制品仓库,用来存储镜像等内容。它非常强调自身的安全性。
Harbor整体的学习与使用成本较低,也提供大量的界面化工具,主要存在新老版本的兼容问题。对于新团队,强烈建议直接使用Harbor。
Dragonfly这个项目利用了P2P的思想,进行镜像、文件的分发,对多机房、多数据中心且传输的文件量大的场景才能突出其价值。
一般情况下我们无需考虑。
OPA是一个很有意思的项目,我们可以看看它的实际构成。一个具体的OPA主要包括2块:
Policy即策略,例如大于某个值时执行策略;而Data则是配置Policy的具体数据,例如将Policy的某个值设置为10。组合了Policy+Data,这个策略才能真正地执行,可以使用OPA的库或者服务。
OPA的思想对项目的可读性和扩展性很有意义,尤其是对于一些需要大量策略配置的服务,如Envoy。
TUF是软件更新系统的行业事实上的标准,对于实际开发的意义不大。
Notary是一个允许任何人信任任意数据集合的项目,是TUF的一个具体实现。目前主要应用在镜像上。
Falco是一个保证运行时安全的项目,用来检测云原生运行时的各种异常与安全问题。
运行时的安全问题是系统安全的最后一道防线,往往需要研发团队紧急处理。
SPIFFE 定义了服务的认证标准和认证信息的标准,SPIRE 是它的一个具体实现。
这块内容仍处于初期,我们了解即可。
今天,我们走马观花地查看了Provisioning层的项目,大家重点关注Harbor和KubeEdge即可。其中Harbor操作难度低,可以快速上手使用;而KubeEdge面向的边缘计算领域比较窄,适用于特定人群。
到这里,我们的CNCF之旅已经基本完成了。后续有机会,我会挑选几个受欢迎的项目做细致的分析。
关于Go语言的垃圾回收Garbage Collector
,相信大家都在网上看过很多相关的文章:有的是科普性质的讲解,有的是直接对着源码的分析,也有的是与其余语言的对比。但文章往往具有时效性,或多或少与最新的Go语言实现有一些偏差。
从这篇开始,我将分析更具权威和参考价值的官方资料,让大家对Go的GC有深刻而长远的认识。
我们今天看的这一篇文章,来自内存管理大师理查德·哈德森的一次分享。我将挑选其中的一些关键点来描述。
《Go垃圾回收之旅》原文链接 - https://go.dev/blog/ismmkeynote
今天我们先来看第一块 - 调度概览。
The Go scheduler multiplexes Goroutines onto OS threads which hopefully run with one OS thread per HW thread.
学习GC前,我们先得对Go的GMP模型有一定的了解。这句话包括了三个关键对象:
go
产生的协程这三者,分别对应GMP模型中的G、M、P。
我们再聚焦于两个关键的描述:
关于GMP,我们到这里浅尝辄止。更多的实现细节,会在后面单独开启一个系列。
我们继续看理查德·哈德森的分享 - https://go.dev/blog/ismmkeynote, 原文中有这么一句描述:
Go is a value-oriented language.
理解value-oriented与reference-oriented的差别,对我们学习与理解GC意义很大。以官方tar
包中的Reader
为例:
type Reader struct {
r io.Reader
pad int64 // Amount of padding (ignored) after current file entry
curr fileReader // Reader for current file entry
blk block // Buffer to use as temporary local storage
// err is a persistent error.
// It is only the responsibility of every exported method of Reader to
// ensure that this error is sticky.
err error
}
为了方便理解,举一个最简单的实现:
Reader
结构体里的所有数据(各个field)都是放在 栈上连续的内存Reader
结构体保存在堆空间里,而在栈上分配一个指针,记录Reader
的起始地址,方便找到。所以,两者的内存分配大致情况如下:
强调一下,上面只是一个最简单的实现,实际情况会复杂得多。比如说复杂情况下的reference-oriented:
两种实现各有优劣。为了加深大家的印象,我这边以 运行时 作为考量点,来分析分析:
运行时 可以简单理解为: 在一个程序开始运行后,内部的数据量越多、数据变化越频繁、运行时间越长,运行时就越复杂,需要在内存中维护大量的信息。
再次提醒:以上内容只是为了更好地描述value-oriented,简化了问题,不可以偏概全。比如,在Go语言中会涉及到变量的逃逸分析,可能会分配到堆上。
本篇文章需要大家对 程序的堆与栈 有一定的基础了解,如果有同学不太清楚,建议花几分钟的时间去补一补。
文中提到了两个value-oriented的价值,建议了解大致原理即可,对理解GC意义不大。