首页 文章 精选 留言 我的

精选列表

搜索[骁龙8至尊版],共10000篇文章
优秀的个人博客,低调大师

不止Docker:8款容器管理开源方案

Docker诞生于2013年,并普及了容器的概念,以至于大多数人仍然将容器的概念等同于“Docker容器”。 作为第一个吃螃蟹的人,Docker设置了新加入者必须遵守的标准。例如,Docker有一个大型系统镜像库。所有的替代方案都必须使用相同的镜像格式,同时试图改变Docker所基于的整个堆栈的一个或多个部分。 在此期间,出现了新的容器标准,容器生态系统朝着不同方向发展。现在除了Docker之外,还有很多方法可以使用容器。 在本文中,我们将介绍以下内容: 将Chroot、cgroups和命名空间作为容器的技术基础 定义Docker所基于的软件堆栈 说明Docker和Kubernetes需要坚持和遵守的标准 介绍替代解决方案,这些解决方案尝试使用具有更好更安全的组件来替换原始Docker容器。 容器的软件堆栈 像Chroot 调用、 cgroups 和命名空间等 Linux 特性帮助容器在与所有其他进程隔离的情况下运行,从而保证运行时的安全性。 Chroot 所有类似Docker的技术都起源于类似Unix操作系统(OS)的根目录。在根目录上方是根文件系统和其他目录。 从长远来看,这是很危险的,因为根目录中任何不需要的删除都会影响整个操作系统。这就是为什么存在一个系统调用chroot()。它创建了额外的根目录,例如一个用于运行遗留软件,另一个用于包含数据库等等。 对于所有这些环境,chroot似乎是一个真正的根目录,而是实际上,它只是将路径名添加到任何以/开头的名字上。真正的根目录仍然存在,并且任何进程都可以引用指定根目录以外的任何位置。 Linux cgroups 自2008年2.6.24版本以来,Control groups (cgroups)一直是Linux内核的一项功能。Cgroup将同时限制、隔离和测量多个进程的系统资源(内存、CPU、网络和I/O)使用情况。 假设我们想阻止用户从服务器发送大量电子邮件。我们创建了一个内存限制为1GB、CPU占用率为50%的cgroup,并将应用程序的 processid添加到该组中。当达到这些限制时,系统将限制电子邮件发送过程。它甚至可能终止进程,这取决于托管策略。 Namespaces Linux命名空间是另一个有用的抽象层。命名空间允许我们拥有许多进程层次,每个层次都有自己的嵌套“子树(subtree)”。命名空间可以使用全局资源,并将其呈现给其成员,就像它是自己的资源一样。 具体来看,Linux系统开始时的进程标识符(PID)为1,并且所有其他进程将包含在其树中。PID命名空间允许我们跨越一棵新树,它拥有自己的PID 1进程。现在有两个值为1的PID,每个命名空间可以产生自己的命名空间,并且相同的过程可以附加了几个PID。 子命名空间中的一个进程将不知道父级的进程存在,而父命名空间将可以访问整个子命名空间。 有七种类型的名称空间:cgroup、IPC、网络、mount、PID、用户和UTS。 Network Namespace 一些资源是稀缺的。按照惯例,有些端口具有预定义的角色,不应用于其他任何用途:端口80仅服务于HTTP调用,端口443仅服务于HTTPS调用等等。在共享主机环境中,两个或多个站点可以监听来自端口80的HTTP请求。第一个获得该端口的站点不允许任何其他应用程序访问该端口上的数据。第一个应用程序在互联网上是可见的,而其他所有应用程序将不可见。 解决方案是使用网络命名空间,通过网络命名空间,内部进程将看到不同的网络接口。 在一个网络命名空间中,同一端口可以是开放的,而在另一个网络命名空间中,可以关闭该端口。为此,我们必须采用额外的“虚拟”网络接口,这些接口同时属于多个命名空间。中间还必须有一个路由器进程,将到达物理设备的请求连接到相应的名称空间和其中的进程。 复杂吗?这就是为什么Docker和类似工具如此受欢迎。现在让我们来介绍一下Docker,以及它的替代方案。 Docker: 人人可用的容器 在容器统治云计算世界之前,虚拟机非常流行。如果你有一台Windows机器,但想为iOS开发移动应用程序,你可以购买一台新的Mac,或者将其虚拟机安装到Windows硬件上。虚拟机也可能是笨重的,它们经常吞噬不需要的资源,而且启动速度通常很慢(长达一分钟)。 容器是标准软件单元,具有运行程序所需的一切:操作系统、数据库、镜像、图标,软件库、代码和所需的其他组件。容器的运行也与所有其他容器,甚至与操作系统本身隔离。与虚拟机相比,容器是轻量级的,所以它们可以快速启动,并且容易被替换。 要运行隔离和保护,容器需要基于Chroot、cgroups和命名空间。 容器的镜像是在实际机器上形成应用程序的模板,能够根据单个镜像创建尽可能多的容器,一个名为Dockerfile的文本文件包含了组装镜像所需的所有信息。 Docker带来的真正革命是创建了Docker镜像仓库和开发了Docker引擎,这些镜像以相同的方式在各地运行,作为第一个被广泛采用的容器镜像,形成了一个不成文的世界标准,所有后来的入局者都必须关注它。 CRI and OCI OCI 全称为Open Container Initiative,它发布镜像和容器的规范。它于2015年由Docker发起,并被微软、Facebook、英特尔、VMWare、甲骨文和许多其他行业巨头接受。 OCI还提供了规范的一个实现,被称为runc ,它可以直接使用容器,创建并运行它们等。 容器运行时接口(Container Runtime Interface,简称CRI)是一个Kubernetes API,它定义了Kubernetes如何与容器运行时交互。它也是标准化的,所以我们可以选择采用哪个CRI实现。 用于CRI和OCI的容器的软件堆栈 Linux是运行容器的软件堆栈中最基本的部分: 请注意,Containerd和CRI-O都坚持CRI和OCI规范。对于Kubernetes而言,这意味着它可以使用Containerd或CRI-O,而用户不会注意到其中的区别。它还可以使用我们现在要提到的任何其他替代方案——这正是创建和采用了OCI和CRI等软件标准的目标。 Docker软件堆栈 Docker的软件堆栈包括: docker-cli,面向开发者的Docker命令行界面 containerd,最初由Docker编写,后来作为一个独立的项目启动; 它实现了CRI规范 runc,它实现了OCI规范 容器(使用chroot、cgroups、命名空间等) Kubernetes的软件堆栈几乎是相同的;Kubernetes使用CRI-O,而不是Containerd,这是由Red Hat / IBM和其他人创建的CRI实现。 containerd containerd作为一个守护程序在Linux和Windows上运行。它加载镜像,将其作为容器执行,监督底层存储,并负责整个容器的运行时间和生命周期。 Containerd诞生于2014年,一开始作为Docker的一部分,2017年成为云原生计算基金会(CNCF)中的一个项目,并于2019年年初毕业。如果你想了解一些Containerd的使用技巧,欢迎查看下方的文章: 配置 containerd 镜像仓库完全攻略 runc runc是OCI规范的参考实现。它创建并运行容器以及其中的进程。它使用较低级别的Linux特性,比如cgroup和命名空间。 runc的替代方案包括Kata-Runtime、GVisor和CRI-O。 Kata-Runtime使用硬件虚拟化作为单独的轻量级VM实现OCI规范。它的运行时与OCI、CRI-O和Containerd兼容,因此它可以与Docker和Kubernetes无缝工作。 Google的gVisor创建包含自己内核的容器。它通过名为runsc的项目实现OCI,该项目与Docker和Kubernetes集成。有自己内核的容器比没有内核的容器更安全,但它不是万能的,而且这种方法在资源使用上要付出代价。 CRI-O是一个纯粹为Kubernetes设计的容器堆栈,是CRI标准的第一个实现。它从任何容器镜像仓库中 提取镜像,可以作为使用Docker的轻量级替代方案。 今天它支持runc和Kata Containers作为容器运行时,但也可以插入任何其他OC兼容的运行时(至少在理论上)。 它是一个CNCF孵化项目。 Podman Podman是一个没有守护进程的Docker替代品。它的命令有意与Docker尽可能兼容,以至于您可以在CLI界面中创建一个别名并开始使用单词“Docker”而不是“podman”。 Podman的目标是取代Docker,因此坚持使用相同的命令集是有意义的。Podman试图改进Docker中的两个问题。 首先,Docker总是使用内部守护进程执行。守护进程是在后台运行的单进程。如果它失败了,整个系统就会失败。 第二,Docker作为后台进程运行,具有root权限,所以当你给一个新的用户访问权时,你实际上是给了整个服务器的访问权。 Podman是一个远程Linux客户端,可直接从操作系统运行容器。你也可以以rootless模式运行它们。它从DockerHub下载镜像,并以与Docker完全相同的方式运行它们,具有完全相同的命令。 Podman以root以外的用户身份运行命令和镜像,所以它比Docker更安全。另一方面,有许多为Docker开发的工具在Podman上是不可用的,如Portainer和Watchtower。摆脱Docker意味着放弃你之前建立的工作流程。 Podman的目录结构与buildah、skopeo和CRI-I类似。它的Pod也非常类似于KubernetesPod。 Linux容器:LXC和LXD LXC(LinuX Containers)于2008年推出,是Linux上第一个上游内核的容器。Docker的第一个版本使用了LXC,但在后来的发展中,由于已经实现了runc,所以LXC被移除了。 LXC的目标是使用一个Linux内核在一个控制主机上运行多个隔离的Linux虚拟环境。为此,它使用了cgroups功能,而不需要启动任何虚拟机;它还使用命名空间,将应用程序与底层系统完全隔离。 LXC旨在创建系统容器,几乎就像你在虚拟机中一样——但硬件开销很小,因为这些硬件是被虚拟化的。 LXC不模拟硬件和软件包,只包含需要的应用程序,所以它几乎以裸机速度执行。相反,虚拟机包含整个操作系统,然后模拟硬件,如硬盘、虚拟处理器和网络接口。 所以,LXC是小而快的,而虚拟机是大而慢的。另一方面,虚拟环境不能被打包成现成的、可快速部署的机器,而且很难通过GUI管理控制台进行管理。LXC要求技术人员有很高的技术水平,并且优化后的机器可能与其他环境不兼容。 LXC VS Docker LXC就像Linux上的一个增压chroot,它产生的“小”服务器启动更快,需要更少的RAM。然而,Docker提供了更多特性: 跨机器的可移植部署:使用一个版本的Docker创建的对象可以传输并安装到任何其他支持Docker的Linux主机上。 版本控制:Docker可以用一种类似git的方式跟踪版本——您可以创建容器的新版本,将它们回滚等等。 重复使用组件:使用Docker,您可以将已经创建的包堆叠到新包中。如果您想要一个LAMP环境,可以安装一次它的组件,然后将它们作为预先制作的LAMP镜像重新使用。 Docker镜像存档:可以从专用站点下载数十万个Docker镜像,并且很容易将新镜像上传到这样的镜像仓库中。 LXC面向系统管理员,而Docker更面向开发人员。这就是Docker更受欢迎的原因所在。 LXD LXD有一个特权守护进程,它通过本地UNIX socket和网络(如果启用)公开REST API。您可以通过命令行工具访问它,但它总是使用REST API调用进行通信。无论客户端是在本地机器上还是在远程服务器上,它的功能都是一样的。 LXD可以从一台本地机器扩展到几千台远程机器。与Docker类似,它是基于镜像的,所有更流行的Linux发行版都可以使用镜像。Ubuntu的公司Canonical正在资助LXD的开发,因此它将始终运行在Ubuntu以及其他类似Linux操作系统的最新版本上。LXD可以与OpenNebula和OpenStack标准无缝集成。 从技术上讲,LXD是站在LXC的肩膀上(两者都使用相同的liblxc库和Go语言创建容器),但LXD的目标是改善用户体验。 Docker会永远存在吗? Docker拥有1100万开发者、700万个应用程序和每月130亿次的镜像下载。如果仅仅说Docker仍然是领导,那就太轻描淡写了。然而,在这篇文章中,我们已经看到,现在已经有许多产品可以取代Docker软件栈的一个或多个部分,并且通常情况下没有兼容性问题。而且与Docker提供的服务相比,其他软件的主要目标是安全性。 原文链接: https://community.suse.com/posts/beyond-docker-a-look-at-alternatives-to-container-management-14411837

优秀的个人博客,低调大师

8个常用的JavaScript数组方法

数组(Array)是JavaScript中内置的全局对象,在构建诸如商品列表等组件(Component)时,时常用到。除了常见的push、pop、indexOf等方法,JS还提供了一些诸如过滤、规约等流处理方法,非常类似于Java的Stream库。 const students = [ { name: 'Alice', score: 100 }, { name: 'Bob', score: 90 }, { name: 'Trunp', score: 80 }, { name: 'Biden', score: 70 }, { name: 'Joe', score: 60 }, { name: 'Sunshine', score: 50 }, { name: 'Elon', score: 40 }, { name: 'Jack', score: 30 }, ]; filter 过滤方法,返回符合条件的元素。 //返回成绩大于75的高分学生 const highScores = students.filter(stu => stu.score > 75); console.log(highScores); 结果: [ { name: 'Alice', score: 100 }, { name: 'Bob', score: 90 }, { name: 'Trunp', score: 80 } ] 更好的是,由于const类型的值,都是不可变量,因此这些操作的返回的都是一个新对象,并不会影响到原值。 map 将数组内的item转化成另一种对象,类似于Java的Fucntion<T,R>接口。 //返回全部对象的name属性 const names = students.map(stu => stu.name); console.log(names); 结果: [ 'Alice','Bob', 'Trunp','Biden','Joe', 'Sunshine','Elon','Jack'] find 类似于filter方法,但返回第一个符合条件的元素。filter返回一个数组,find返回一个object。 //返回name长度为4的第一个对象 const foundedOne = students.find(stu=>stu.name.length === 4); console.log(foundedOne); 结果: { name: 'Elon', score: 40 } 由结果可见,虽然elon和jack都符合条件,但只返回了elon。 forEach 遍历数组内全部元素。 //打印元素 students.forEach(item=>console.log(`stu-name=${item.name},stu-score=${item.score}`)); 结果: stu-name=Alice,stu-score=100 stu-name=Bob,stu-score=90 stu-name=Trunp,stu-score=80 stu-name=Biden,stu-score=70 stu-name=Joe,stu-score=60 stu-name=Sunshine,stu-score=50 stu-name=Elon,stu-score=40 some 当数组中有一个符合条件,则返回true,否则返回false。 //是否至少有一个name为Jack的 const isSome = students.some(item=>item.name === 'Jack'); console.log(isSome); 结果:true every 功能类似于some,但要求每一个元素都符合条件才返回true。 //是否score都大于70 const isEvery = students.every(item=>item.score > 70); console.log(isEvery); 结果:false reduce 规约函数。在MDN中给出的API可以简化为,reduce(callback(accumulator,current),initValue)。它有两个参数,第一个是回调函数,第二个initValue是初始值,可选的。current表示数组内的元素,即当前值。 值得一说的是accumulator这个参数,它是中间态的值,一个累加器。换句话数,reduce函数是有状态的,即非纯函数,在多线程执行的时候,需要做一致性处理,否则可能会得到意外值。当然JavaScript是单线程执行的,所以可不考虑,但是用到类似于Java的语言中则需小心。 //求取全部score之和 const result = students.reduce( (accumulator, current) => accumulator + current.score, 0 ); console.log(result); 以上函数中,我们通过accumulator加上每一个元素值,获得最终结果。 结果:520。 includes 是否包含指定的元素值。 const isIncludes = students.includes({ name: 'Jack', score: 30 }); console.log(isIncludes); 结果:false。 虽然提供了和最后一个元素的一摸一样的{name: 'Jack', score: 30},但仍然返回false,说明两个对象不是指向同一个引用。 以上,都是很实用的方法,他们使得原来需要很多语句才能做的事情,通过一个简单的调用,即可得出结果。

优秀的个人博客,低调大师

Apache IoTDB 系列教程-8:文件同步工具

在官网用户手册的系统工具(System Tools)一栏,有一个同步工具(Sync Tool),有很多人问这个东西怎么用,延迟是多少,今天就介绍一下这个工具的使用场景、基本原理和测试技巧。 正文 2439 字,预计阅读时间 7 分钟。 使用场景 某公司有多个电厂,每个电厂内部署了一个 IoTDB,负责监控电厂内多个设备的运行状态。各个电厂间数据不互通。这个时候公司想建一个云平台,汇总所有电厂的数据进行分析(这里有一个前提,云平台的数据分析主要针对长期历史数据,对数据的实时性要求不高)。这时候就可以用这个文件同步工具了。 文件同步工具的定位:将一个 IoTDB 的 Schema 和数据文件(TsFile)同步至另一个 IoTDB 中,同步过程会有一定延迟,具体延迟取决于负载和配置。 基本原理 通过名字应该能看出来,这个工具的同步粒度是数据文件,而不是每一个数据点。这也就导致同步的最长延迟是一个数据文件的生成耗时(从创建文件到封口)。因为发送端必须等一个文件生成好才会同步,否则传过去半个文件也没法解析。传文件类似 scp,相对同步每条数据的好处就是避免了数据的解析和重新导入。 我们把文件同步涉及到的两个 IoTDB 称为发送端、接收端。 写入流程 为了更好的理解数据文件的生成耗时,需要简单介绍一下写入流程。 IoTDB 采用了 LSM 结构,数据先写到内存缓冲区 memtable 中,memtable 达到一定大小会落盘,多个 memtable 会对应一个数据文件。 举个例子,某个存储组有 1 个时间序列,写入频率为 1 秒,每个数据点是 16 字节。一个 memtable 大小为 160 字节,TsFile 文件大小为 200 字节。存储组刚开始有一个空的 TsFile 可供写入。 (1)memtable 第一次存满 10 个数据点时,提交一个异步刷盘任务(追加到当前正在写入的 TsFile 中),同时检查 TsFile 大小,这个时候还是 0 字节,先不关文件。 (2)异步的刷盘任务开始执行,刷完之后 TsFile 变成了 200 字节。 (3)memtable 第二次存满 10 个数据点时,提交一个异步刷盘任务,同时检查 TsFile 大小,发现到了 200 字节,于是就标记关文件。 (4)异步刷盘任务开始执行,刷完之后把当前 TsFile 关掉。 在这个例子里,写满 2 个 memtable (20条数据) 关闭一次文件,写入频率为 1 秒,文件的生成耗时是 20 秒左右。 同步流程 发送端定时检查本地有没有新创建的 Schema 和新生成的完整的数据文件,如果存在,就发给接收端。同步的延迟基本就是 max(同步检查间隔,文件生成耗时)。 在 iotdb-sync-client.properties 配置文件中,有一个参数sync_period_in_second,这个控制发送端检查的频率。假如配置 60 秒,那同步的最长延迟就是 60秒,如果配置 10秒,那延迟就是 20秒(一个文件的生成耗时)。可以看到,同步延迟跟配置有关系,跟写入频率也有关系。 配置文件里的 sync_period_in_second 可以配的比较小,没啥大问题。主要问题是 TsFile 的生成间隔,这个由 memtable_size_threshold 和 tsfile_size_threshold 控制,这两个参数,尤其是 memtable 越大,历史数据查询越快。因此,同步能达到的最低延迟和查询性能之间需要平衡。 一个比较简单的查看自己系统里文件的生成速率,可以到数据目录 data/data/存储组{/分区} 看 .resource 文件的最后修改时间间隔。 测试同步 在一个机器测试同步,示例脚本为 linux 环境,版本 0.10.1。先下载二进制包,解压缩两遍重命名,一个 sender,一个 receiver。 启动接收端 cdreceiver## 配置conf/iotdb-engine.properties中的is_sync_enable=true##启动接收端 IoTDBnohup./sbin/start-server.sh>/dev/null 2>&1 &##启动接收端CLI,默认用root 用户连本地6667 端口./sbin/start-cli.sh 启动发送端,准备数据 cd sender## 配置conf/iotdb-engine.properties中的 rpc_port=6668conf/iotdb-sync-client.properties 中的 sync_period_in_second=10##启动iotdbnohup ./sbin/start-server.sh >/dev/null 2>&1 &## 启动发送进程nohup./tools/start-sync-client.sh>/dev/null2>&1&##启动发送端CLI,注意,改到 6668 端口了./sbin/start-cli.sh -h 127.0.0.1 -p 6668 -u root -pw root##输入insert into root.turbine1.d1(timestamp,s1,s3) values(2,1,3);flush(这个是精髓,强制把memtable刷盘,文件封口) 接收端验证数据 ## 在接收端 CLI 中输入select*fromroot 如果想自己配置,需要先把 enable_parameter_adapter 置为 false,不然系统会自动调 memtable 和 tsfile 大小。 具体可参考用户手册,也可点阅读原文跳过去。 http://iotdb.apache.org/zh/UserGuide/V0.10.x/System%20Tools/Sync%20Tool.html 总结 文件同步适合对实时性要求没那么高的数据汇总,备份。秒级或分钟级的同步就需要换方案了。在实验中遇到数据没同步过去的,要么是同步的定时检查间隔设置的过长了,要么是文件没关闭,现在还没有定时关文件的机制,需要手动调用 flush。对了,提示一个东西,start-cli.sh 脚本也可以连远端的 iotdb,加上 -h-p-u -pw 参数就行了。 本文分享自微信公众号 - IoTDB漫游指南(Apache-IoTDB)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册