「CEPH」- Filestore

问题描述
基于 PCIE 的 SSD 或者基于 NVMe 的 SSD 在技术以及成本上没有可行性;
解决方案
FileStore 是 Ceph 的原始存储实现之一,并且是使用最广泛的实现方式。当 2004 年 Ceph 项目启动时,Ceph 完全依靠机械硬盘进行存储;
原理简述
FileStore 不是直接与原子块设备进行交互,而是与文件系统(通常为 xfs)进行交互。当对象存储处理完对象的语义并将其传递给 FileStore 时,FileStore 会将 PG 视为目录,将对象视为文件,并将元数据视为 XATTR 或 omap 条目,然后将剩下的操作交给文件系统处理,保证数据落盘;

数据的写入分为两个部分:Ceph 日志;Ceph 数据;
第一步、数据写入日志
用户数据文件在客户端写入 Ceph 集群时,将被客户端分割,生成多个以 4MB 为单位的对象。生成的每个对象将来都需要写入 OSD,但首先是写入日志。
Ceph 日志是事物日志系统。Ceph 采用的是全日志系统,即将所有数据存放在日志中。当有突发的大量写入操作时,Ceph 可以先把一些零散的、随机的 I/O 请求保存到缓存中并进行合并,然后再统一向内核发起 I/O 请求。以提高效率,但是一旦 OSD 崩溃,缓存中的数据就会丢失,所以数据在还未写入硬盘时,都会记录到事务日志系统中。当 OSD 崩溃后重新启动时,自动尝试从事务日志系统恢复因崩溃丢失的缓存数据。
写日志有两种模式: 1)Parallel 是日志和磁盘数据同时写; 2)Writeahead 是先写日志,只要日志写成功就返回,后台周期会同步日志中的写操作,实现落盘。其优点是能合并较小 I/O 请求,形成顺序写盘,提高 IOPS。
日志,是提高 FileStore 性能的关键因素,这些都是调优的考量参数: 2)日志同步时间的设置也会影响 Ceph 的性能; 1)日志系统空间大小代表能缓存的数据量; 3)计算日志大小的公式:如果 SSD 的预期吞吐量为 2GB/s,并且文件存储最大同步间隔为 10s,则日志大小应为 40GB(2×2×10); 3)在生产环境中,我们通常使用 SSD 来单独存储日志文件,以提高 Ceph 读写性能;
第二步、日志写入磁盘
在 FileStore 存储模式中,每一个对象都要通过 FileStore 的相关功能写入底层的磁盘。
Ceph 数据就是 Ceph 的对象数据,其中包含元数据。Ceph 在写完日志后,返给 OSD 写完成消息(Writeahead 模式),然后处理下一次写请求。这意味着数据当前保留在日志系统中,还没有真正落入后端的存储磁盘。Ceph OSD 进程根据参数设置的时间定期向文件系统同步数据。此操作[……]

READ MORE

「Ceph」- 客户端

客户端类型
Ceph 支持多种客户端类型,所有的用户数据都是通过客户端进行交互的。每种客户端底层都依赖 Ceph 不同标准的客户端接口:S3/Swift、RBD、CephFS;

Ceph RDB 提供了块存储,其安装方式类似于物理存储驱动器。Ceph RGW 通过其自己的用户管理器提供具有 S3 兼容和 Swift 兼容的 RESTful 接口的对象存储服务。但是,所有 Ceph Client 底层都使用 RADOS 协议和存储集群进行交互;
Ceph 支持当前主流的数据访问方式,比如 NFS、iSCSI、RBD、Filesystem、S3 等等;
librados
librados(分布式对象存储系统 RADOS 库),是对 RADOS 的抽象和封装,并向上层提供 API,用于与 RADOS 系统交互。Client 调用本机上的 librados,再由后者通过 socket 与 RADOS 的节点通信并完成各种操作;
基于 LIBRADOS 实现的兼容 Swift 和 S3 的存储网关系统 RADOSGW; 基于 LIBRADOS 实现的块设备驱动 RBD; 基于 LIBRADOS 实现的 POSIX 分布式文件系统 CephFS;
我们也能够借助 librados 来编写自己的应用,实现与 RADOS 的直接交互;
对象存储接口
现代应用程序需要具有异步通信功能的简单对象存储接口。Ceph Cluster 提供了具有异步通信功能的简单对象存储接口。该接口支持对整个集群中对象的直接、并行访问;
通过对象接口,能够执行以下操作: 1)池操作 2)快照 3)读 / 写对象 4)创建 / 设置 / 获取 / 删除 XATTR 5)创建 / 设置 / 获取 / 删除键 / 值对
访问集群的必要参数
不论哪种存储客户端访问方式,它们都要有以下几个必备要素: 1)Ceph 配置文件和 Ceph Monitor 地址 2)存储池名称 3)用户名和密钥的路径
客户端的 Watch/Notify 机制
在 Ceph Cluster 中,Watch/Notify 机制用于在不同客户端之间进行通信,使各客户端的状态保持一致;
Watch/Notify 机制需关联到特定对象。当多个客户端接收到同一个对象后,任一客户端发送通知消息对该对象所在的 OSD 消息进行复制,进而转发给所有的客户端;

当某客户端不是以只读方式打开对象时会接收消息,并主动发送通知消息到其他客户端,同时接收来自其他客户端的消息。而且该客户端也会收到自己发出去的通知消息,并判断此通知是不是自己发出的消息对应的回应消息;
客户端的独占锁
如果一个 RBD 映射到多个客户端,独[……]

READ MORE

「CEPH」- 概念术语:放置组(Placement Group,PG)

问题描述
Ceph 可通过副本或纠删码实现数据持久性,通过清洗或循环冗余校验保证数据完整,实现复制、重新平衡和故障恢复。
但是,在 EB 级存储集群中,存储池可能存储数百万个数据对象。数据的复制、移动,会存在性能问题。
解决方案
Ceph 通过将 Pool 划分为 PG(Placement Group,放置组)来解决性能瓶颈问题。PG 是一个非常重要的概念,对其进行合理设置可以提高集群的性能。有效地分配 PG,以提高集群性能;
原理简述
Pool, PG and Data
Pool 被分隔为 PG ,即 PG 是 Pool 的子集 PG 是数据对象的集合,即 PG 中包含数据对象。
例如,每个 Pool 分配 PG * 100,意味着每个 PG 大约包含 Pool 中 1% 的数据。
数据保存在 Pool 中,而 Pool 被分为多个 PG,而 PG 其中包含多个 Object; 最终 PG 将其中的数据存储在 OSD 中; PG 是若干 Object 的逻辑集合; PG 会被复制和分布到多个 OSD 上; 以 PG 为单位,Ceph 来进行数据的复制、副本;

CRUSH算法用于在Ceph中定位存储数据的位置,并计算放置组中的OSD目标集。CRUSH算法将每个对象放入一个放置组,然后将每个放置组存储在一组OSD中。
数据读写的大致过程
系统管理员在创建或修改 Pool 时,设置 PG 数。
Ceph将一个存储池划分为一系列放置组,每一个客户端对象都会分配给一个放置组,然后将该放置组分配给一个主OSD。由于Ceph通过设置副本数量或纠删码级别对数据进行保护,因此Ceph会根据副本数或者纠删码中校验盘的数量选择OSD,并将主OSD中的放置组复制到从OSD。如果主OSD发生故障或集群做了数据重新平衡,Ceph可以对集群中现有非主OSD上保存的放置组数据进行复制或移动。因为有了放置组,对象所在的OSD位置就清楚了。即便是OSD有损坏,你也不必为每个对象单独寻址。CRUSH算法会结合Cluster Map和集群的状态将放置组均匀、伪随机地分配给集群中的OSD(包括主OSD和从OSD)。

PG 在 OSD 间复制,保证集群数据安全的方法: 1)CRUSH 算法将 OBJ 00 分配给 PG 00,并且将 PG 00 分配给 OSD 01,让 OSD 1 作为 Primary OSD。 2)CRUSH 算法计算出 OSD 04 是 PG 00 的 Secondary OSD,则 Primary OSD 01 将 PG 00 内容数据复制到 OSD 01 和 OSD 04。
数量配置
集群 PG 总数
集群 PG 总数 = (OSD 总数)×(每[……]

READ MORE

「CEPH」- Placement Group Placement

PGP(Placement Group for PlacementPurpose)决定对象分布在哪些 OSD 上。参数 pgp_num 表示 PGP 的可操作值;
调整 pgp_num 而带来的变化
如果增大 PGP 值,PG 内的对象会重新计算,集群中的数据将开始做重新分布;
现在,创建存储池 Pool(pg_num=1, pgp_num=1) 即只有 PG * 1 和 PGP * 1,并且 PG 内有 100 个对象:

假设数据冗余 replica=3,数据会分布在 3 个 OSD 上,设这三个 OSD 编号为 1、3、8。那么,这些数据的位置在创建存储池的时候都会被固定;

随后调整 Pool(pg_num=2, pgp_num=1),即新增 PG * 1,而且这个 PG 内分割了原有 PG 内的一部分对象,也就是说两个 PG 共同存储 100 个对象。然而观察 PG 的分布,发现这两个 PG 对象的 OSD 编号仍然是 1、3、8,即增加 PG 的数量不改变原有的 OSD 映射关系;

而调整 Pool(pg_num=2, pgp_num=2),即增加 PGP * 1,现在 PG 内的对象并没有发生变化,只是其中一个 PG 中对象的 OSD 编号发生了变化,变成了 2、4、9。这时,集群中该 PG 的数据开始从 OSD 1、3、8 向 OSD 2、4、9 迁移;

pg_num vs. pgp_num
pg_num 是存储池中存储对象的“目录数”。pg_num 的增加,会引起 PG 内的对象的分布,即分裂到相同的 OSD 上新生成的 PG 中;
pgp_num 是存储池中放置组内的 OSD 分布组合个数。pgp_num 的增加会引起部分 PG 在 OSD 上的分布变化,但是不会引起 PG 内对象的变动;[……]

READ MORE

「Ceph」- 概念术语:Pool,存储池

概述介绍
Pool 是存储对象的逻辑分区,Ceph Cluster 将数据对象存储在 Pool 中(逻辑分区),以实现不同数据的逻辑隔离;
管理员,能为特定类型的数据(例如块设备、对象网关)创建多个 Pool 实例,或使用 Pool 将一组用户与另一组用户分开;
客户端,当读取或写入数据时,总是连接到某个 Pool。Client 指定 Pool Name、用户和密钥,因此该池看起来像是一个逻辑分区,便于对数据对象进行访问控制;
相关概念
池类型
副本,通过数据复制来提供数据冗余;纠删码,通过校验码来确保数据冗余,类似 RAID-5 技术; 存储池类型定义了创建池时的数据持久化方法。存储池类型对客户端完全透明,客户端不需要关心
CRUSH 规则集
CRUSH 扮演着另一个重要角色,可用于检测故障域和性能域。CRUSH 可以按存储介质类型识别 OSD。CRUSH 使 OSD 能够跨故障域存储对象副本。例如,对象副本可能会存储在不同的服务器机房、机架和节点中。如果集群的很大一部分节点发生故障(例如机架),集群仍可以降级状态运行,直到集群恢复正常为止。此外,CRUSH 能够使客户端将数据写入特定类型的硬件,例如 SSD;
容量大小
参数 target_size_bytes 可以对存储池的容量进行硬限制,即限制存储池最大使用容量;
缓存分层(Cache Tiering)
缓存分层,通过将部分数据保存在缓存层(通常为更快的存储硬件),为 Ceph Client 提供更好的 IO 性能;
Writeback Mode
当客户端写数据时: 1)数据写到缓存层中,客户端就会立刻收到确认回复; 2)基于所配置的刷新 / 删除(flush/evict) 策略,数据从缓存层迁移到存储层, 3)最后被缓存分层代理〈cache-tiering agent) 从缓存层中删除;
当客户端执行读操作时: 1)数据通过缓存分层代理,先从存储层传输到缓存层,然后发送给客户端; 2)数据会保留在缓存层直到变为无效数据或冷数据;
writeback 模式的缓存层是用于可变数据,如图片或视频编辑、交易性数据等的理想模式;
Read-only Mode
在该模式下,写操作不会被它处理,而是直接存到后端的存储层;
当缓存分层被配置成 read-on1y 模式时,它只服务于客户端的读操作。当客户端执行读操作时,缓存分层代理从存储层复制请求数据到缓存层; 基于已经配置在缓存层上的策略,过期的 object 会从缓存层中被删除。这种方法适用于多个客户端读取相同的数据时,比如社交媒体内容;
不可变数据是 read-only 缓存层的理想备选方案;[……]

READ MORE

「CEPH」- 纠删码存储池

问题描述
在 Ceph 中,默认的数据保护机制是副本。但是,副本的缺点是需要占用多倍的存储空间来提供冗余。例如,计划搭建 replica=3 的 1PB 可用容量的存储集群,则需要准备 3PB 的存储容量,也就是 +200%,甚至更多。在这种情况下,使用副本机制会使 /GB 的存储费用大幅上升;
解决方案
从 Firefly 发行版本开始,Ceph 推出被称为 Erasure Code(纠删码)的数据保护方法;
原理简述
概述流程
在写入数据时,将每个 Object 划分成更小的 Chunk(数据块),每个块称为 Data Chunk(数据块),再用 Coding Chunk(编码块)对它们进行编码,最后将 Data Chunk 与 Coding Chunk 共同存储到 Ceph Cluster 中的不同故障域中,从而保证数据安全;
纠删码原理
Ceph 可以加载多种纠删码算法。最早且最常用的纠删码算法是 Reed-Solomon。纠删码实际上是前向纠错(Forward Error Correction,FEC)码;
FEC 代码将 K 个 chunk(以下称为块)数据进行冗余校验处理,得到 N 个块数据。这 N 个块数据既包含原数据,也包括校验数据。这样就能保证 K 个块中如果有数据丢失,可以通过 N 个块中包含的校验数据进行恢复;
N=K+M,是纠删码概念的核心在公式。具体地说,变量 K 是数据块即原始数量;变量 M 代表防止故障的冗余块的数量;变量 N 是在纠删码之后创建的块的总数。这种方法保证 Ceph 可以访问所有原始数据,可以抵抗任意 M 个故障。例如,当 K=10, N=16 时,Ceph 会将 6 个冗余块添加到 10 个基本块 K 中。在 M=N–K(即 16–10=6)的配置中,Ceph 会将 16 个块分布在 16 个 OSD 中,这样即使 6 个 OSD 掉线,也可以从 10 个块中重建原始文件,以确保不会丢失数据,提高容错能力;
数据写入过程
在纠删码存储池中,Primary OSD 接收所有写操作。纠删码存储池将每个对象存储为 K+M 个块(K 个数据块和 M 个编码块),配置大小为 K+M,以便 Ceph 将每个块存储到一个 OSD 中。Ceph 将块的等级配置为对象的属性。Secondary OSD 负责将对象编码为 K+M 个块,并将其发送给其他 OSD。Secondary OSD 还负责维护放置组日志的权威版本;
首先,创建 5=3+2 的纠删码存储池,所以需要使用 5 个 OSD 来存储数据块,并 M=2 保证在 2 个 OSD 丢失的情况下恢复数据;
然后,当将包含 ABCDEFGHI 的对象 NYAN 写入纠删码存储池时,纠删码[……]

READ MORE

「Ceph」- 用户、权限、安全

Ceph 提供 Cephx身份验证系统,以保护系统并防止攻击; 注意,Cephx 解决的是系统认证问题,但不提供网络通信时的数据加密。
被认证的对象
1)用户:用户需要完成验证,而后才能访问 Ceph Cluster 数据。比如,某客户端要想执行命令来操作集群,就要有登录Ceph的密钥; 2)进程:集群守护进程间的互相访问,也需要进行认证。这是一种特殊的用户类型MON/OSD/MDS。也就是说,Monitor、OSD、MDS都需要账号和密码来登录Ceph系统。
认证方式
None
针对用户、守护进程,不进行认证;
CephX
针对用户、守护进程,进行认证;

ceph auth cluster required = cephx
ceph auth service required = cephx
ceph auth client required = cephx

Client 访问 Ceph MON 完成身份认证;
Cephx 使用共享密钥进行身份验证,这意味着客户端和Monitor都具有客户端密钥的副本。身份验证协议使双方可以相互证明自己拥有密钥的副本,而无须透露密钥。也就是说,集群确定用户拥有密钥,并且用户确定集群有密钥的副本。
认证过程
客户端的凭证下发

针对请求的认证检查

用户通过Ceph客户端访问Monitor。每个Monitor都可以对用户进行身份验证并分配密钥,因此使用Cephx时不会出现单点故障。Monitor返回身份验证数据,其中包含用于获取Ceph服务的会话密钥。该会话密钥本身已使用用户的永久密钥加密,因此用户只能向Monitor请求服务,然后客户端使用会话密钥从Monitor请求其所需的服务,并且由Monitor向客户端提供密钥,客户端拿到该密钥即可向实际处理数据的OSD发起认证。Monitor和OSD共享一个密钥,因此Monitor提供的密钥可以被集群中的任何OSD或元数据服务器共用。这种身份验证形式可防止有权访问通信介质的攻击者创建虚假消息或更改其他用户的合法消息,但只要该用户的密钥在到期前不被泄露就不会有威胁。要使用Cephx,管理员必须首先设置用户。
用户权限
User Management — Ceph Documentation
allow: 只用于赋予用户 MDS 的 rw 权限;
r: 赋予用户读数据的权限,该权限也是从 monitor 读取 CRUSH map 时必须要有的; w: 赋予用户写入数据的权限; x: 赋予用户调用对和象方法的权限,包括读和写,以及在 monitor 上执行用户身份验证的权限;
class-read: 这是 x 权限的子集,它允许用户调用类的[……]

READ MORE

「CEPH」- CRUSH(Controlled Replication Under Scalable Hashing )

问题描述
数据分布是分布式存储系统的一个重要部分,数据分布算法至少要考虑以下 3 个因素: 1)故障域隔离。同份数据的不同副本分布在不同的故障域,降低数据损坏的风险; 2)负载均衡。数据能够均匀地分布在磁盘容量不等的存储节点,避免部分节点空闲,部分节点超载,从而影响系统性能; 3)控制节点加入离开时引起的数据迁移量。当节点离开时,最优的数据迁移是只有离线节点上的数据被迁移到其他节点,而正常工作的节点的数据不会发生迁移;
解决方案
CRUSH Algorithm,是为解决以上问题而设计的,是 Ceph 的设计精髓。
The CRUSH algorithm enables the Ceph Storage Cluster to scale, rebalance, and recover dynamically.
Using the CRUSH algorithm:Ceph calculates which placement group should contain the object, and further calculates which Ceph OSD Daemon should store the placement group.
原理简述
CRUSH Map,是个结构,该结构描述整个存储集群的结构(诸如 地域、数据中心、区域、机架、主机 等等),是人为定义的。借助于 CRUSH Map 结构,CRUSH 伪随机地存储和检索 OSD 中的数据,并使数据在整个存储集群中均匀分布。
层次结构
在 Ceph Cluster 中,CRUSH 通过简洁而层次清晰的设备描述(CRUSH Map),包括存储集群和副本放置策略,就可以有效地把数据对象映射到存储设备上,且这个过程是完全分布式的,在集群系统中的任何一方都可以独立计算任何对象的位置;
动态变化
另外,大型系统存储结构是动态变化的(存储节点的扩展或者缩容、硬件故障等),CRUSH 能够处理存储设备的变更(添加或删除),并最小化由于存储设备的变更而导致的数据迁移;
特性特征
通过 CRUSH Algorithm 计算来确定数据的存储位置,不需要像以往要查询元数据服务器才能知道数据的位置。这也是 Ceph 不需要元数据服务器的原因。
CRUSH是受控复制的分布式hash算法。 CRUSH算法可以避免单点故障、性能瓶颈以及对Ceph可扩展性的物理限制。 CRUSH 是一种基于伪随机控制数据分布、复制的算法;
数据条带化
存储系统通常都支持 Stripe(条带化)以增加存储系统的吞吐量并提升性能,数据条带化最常见的方式是做 RAID 0 或 “带区卷”,这种数据的分配方式可以弥补单个磁盘读写性能不足的问题。Cep[……]

READ MORE

「Ceph」- 概述数据写入过程

概述介绍
通过 CRUSH 算法,Ceph 实现去中心化;
Ceph Client 根据 CRUSH 来计算它的数据要被写到哪里,以及从哪里读取它所需要的数据。所有这些计算操作都是在 Client 完成的,因此它们不会影响 Ceph Cluster 服务器端的性能。然后 Client 与 Ceph OSD 直接通信;
Ceph OSD 负责创建对象,以及在其他 Ceph Node 上创建这些对象的副本来保证数据的安全性和高可用性。Ceph 还使用 Ceph Mon Cluster 来保证系统的高可用性;
像 Ceph Client 一样,OSD 也连接 Ceph Mon,以检索 Cluster Map 的最新副本。OSD 也使用 CRUSH 算法来计算对象副本的存储位置。在典型的写场景中,Ceph Client 使用 CRUSH 算法来计算对象的 PG ID 和 Primary OSD;
Client
Ceph Client 接口负责和 Ceph Cluster 进行数据交互,包括数据的读写;
Ceph Client 需要以下数据才能与 Ceph Cluster 进行通信: 1)Ceph 配置文件或集群的名称(通常命名为 ceph)、Monitor 地址 2)存储池名称 3)用户名和密钥路径
Ceph 客户端维护对象 ID 和存储对象的存储池名称;
Client <=> Ceph MON
Ceph Client 和其他守护进程使用配置文件发现 Monitor;
为了存储和检索数据: 1)首先,Ceph Client 访问 Ceph Monitor 并检索最新的 Cluster Map 副本,以使知晓 Ceph Cluster 的状态和配置; 2)然后,Ceph Client 通过向 librados 提供对象名称和存储池名称; 3)librados 会使用 CRUSH 算法为要存储和检索的数据计算对象的 PG 和 Primary OSD;
inside Client
2)然后,Client 将数据转化为一个或者多个对象,每个对象都具有 Name 和 Pool name;
3)接着,该对象会被以 PG 的数目为基数做哈希,在指定的 Ceph Pool 中生成最终的 PG;
计算 PG ID 示例,过程如下: 1)Client 输入 Pool ID 和 Object Name(如 pool=liverpool, object-name=john); 2)CRUSH 获得 Pool ID 并 hash(object name) 运算; 3)CRUSH 计算 PG 个数,Hash 取模获得 PG ID; 4)CRUSH 获得已命名 Pool ID([……]

READ MORE

「CEPH」- 消息通信框架

Ceph 客户端和服务器端的消息通信框架有三种:SimpleMessenger、AsyncMessenger XIOMessenger;
SimpleMessenger,使用 TCP Socket 实现。每个 Socket 有两个线程:一个线程用于接收,另一个线程用于发送。但是,这种通信机制在集群规模较大的情况下会创建大量连接,对集群的性能有一定挑战。这种框架比较稳定、成熟;
AsyncMessenger,使用带有固定大小线程池的 TCPSocket 进行连接。该 Socket 数应等于最大副本数或者纠删码块数。这种框架兼容不同的网络传输类型,如 posix、rdma、dpdk。当前,Ceph 默认的消息框架和传输类型为 async+posix。对于 rdma 和 dpdk,其在很多时候技术还不够成熟,商业化过程中的很多问题还没有发现。因此对于追求集群稳定的场景,建议慎重选用该框架;
XIOMessenger,基于开源网络通信库 Accelio 实现。Accelio xio 是与传输相独立的消息抽象,当前在 RDMA(Infiniband 或 Ethernet)上运行,处于试验阶段;[……]

READ MORE

「CEPH」- 部署服务及快速开始

问题描述
该笔记将记录:我们部署测试 Ceph Cluster 的过程,以及相关问题的解决办法;
解决方案
参考 Installing Ceph 文档,以获取安装相关的官方详细说明,这里仅做简单记录;
第一步、版本选择
鉴于我们是测试部署,所以直接部署最新版本 Ceph 17;
第二步、服务部署
通过 ceph-deploy 进行部署(Quickstart)。但是 ceph-deploy 已不再主动维护,其未在 Nautilus 之上的测试。在对比其他部署工具并结合我们的工作场景后,我们决定在测试环境中使用 Cephadm 进行部署(需要 container 与 systemd 来管理);
该部分将记录:通过 cephadm 命令,部署 Ceph 测试集群(学习)的方法,以及相关问题的解决办法;
#1 环境准备工作
对于非生产环境下的Ceph集群的最小化部署,推荐最少配置3个节点。节点角色可以复用。条件允许的情况下,可以配置3 MON+3 OSD+3 Gateway+1Client。
实验环境下服务器的最小配置如下:

Hardware
Ceph OSD
Ceph Mon / Ceph Mgr
Ceph RGW
Ceph MDS

CPU
1vCPU
1vCPU
1vCPU
1vCPU

RAM
16GB+5GB*OSD
1G/Daemon
1G/Daemon
2G/Daemon

DISK
OS * 1 + OSD * N
OS * 1 + 15GB*Daemon
OS * 1 + 5GB*Daemon
2MB*Daemon + Log

Network
1000Mbps * 2
1000Mbps * 2
1000Mbps * 2
1000Mbps * 2

我们需要通过 SSH 连接到各节点服务器上,然后通过执行 cephadm 命令来完成 Ceph Cluster 部署; Ceph 对时间要求很高,建议在部署 Ceph 集群的时候提前配置好 NTP 服务器; Ceph 安装对网络要求不高,但是鉴于 Ceph 源在外国有时候会被屏蔽,解决办法多尝试机器或者代理;
#2 通过 Cephadm 部署
WIP
第三步、配置使用
创建 CephFS 实例
CephFS Quick S[……]

READ MORE

「Electric-Drill」- 学习笔记

强力冲击钻头(780w)

品牌:质造 型号:冲击钻 产地:中国大陆 颜色分类:强劲版冲击钻-出厂配强劲版冲击钻+47 件套强劲版冲击钻+切磨钻头套 电钻类型:冲击钻电压:220V 货号:冲击钻 操作方式:手持式
产品信息
转速:~3000r/min 电压:220v 功率:780w 钻头夹持范围:1.5mm – 13mm

应用场景
支持平钻与 冲击两种模式;
平钻:金属木板瓷砖塑料玻璃铁皮 冲击:混凝土墙面水泥砖红砖天花板水泥柱[……]

READ MORE

「Home Appliance」- 家电

家电,Home Appliance 家用电器,Household Electrical Appliance

Coffee maker
Blender
Mixer
Toaster
Microwave
Crockpot
Rice cooker
Pressure cooker
Bachelor griller (U.K)
Stove
Lamp
Light bulb
Lantern
Torch
Clothes iron
Electric drill
Kettle
Water cooker (U.K)/ Electric kettle/ Hot pot (U.S)
Water purifier
Kitchen hood
Electric guitar
Vacuum cleaner
Electric fan
Evaporative cooler
Air conditioner; air-conditioning; aircondition; air-conditioner; 空调
Oven
Dishwasher
Television
Speaker
Clothes dryer
Washing machine
Refrigerator[……]

READ MORE

「Air Conditioning」- 空调

空调匹数、功率和适用面积对照表
知乎/家电蓝哥/空调匹数、功率和适用面积对照表非常实用建议收藏
空调是比较耗电的产品,功率并非越大越好,而是要与房间面积相匹配。买空调首先要考虑的是房间面积,然后再考虑房间朝向等环境影响,最后选择一款适合匹数的空调。
如果一味追求高速制冷或者制热,小房间买大空调,在使用时,制冷制热速度过快,空调压缩机会频繁启动,耗电量高,造成不必要的浪费;而过分考虑耗电问题,大房间使用小功率空调,就会造成制冷制热速度慢,空调压缩机不停机的现象,影响寿命,耗电不停。
空调匹数
空调的“匹(P)”是功率单位“马力”的俗称,1P=735.499W,通常用匹来表示压缩机的规格。目前主要是以制冷量来计算,因此常说的空调 1P 指的是为空调压缩机输入 735w 功率所对应产生的制冷量;
制冷量
参考 空调制冷量计算公式 说明,以获得详说明。
压缩机的效率约为 0.8~0.85,性能系数(COP)一般在 2.8~3.0 之间,计算下来,1P 空调器的制冷量大约为 2200~2600W,同样也可以计算出 1.5 匹、2 匹空调的制冷量。
一般来说 1P 的制冷量大约为 2000 大卡,换算成国际单位 * 1.162,1P 制冷量为 2000×1.162=2324W;
制冷量 and 制热量 and 房屋朝向
我们以楼层高 2.5 米的房间为例,可按下面公式计算房间所需的制冷量、制热量: 1)制冷量=房间面积×140W~180W 2)制热量=房间面积×180W~240W
上面是参考计算方法,实际情况还应根据房间朝向、装修布置、玻璃窗大小、楼层高低、房间保暖性、密闭程度、居住人数等因素综合权衡。在朝阳、房顶较高或是外墙较多的房间,空调的功率就应适当放大。在低温的地区还应考虑的热冷比及低温启动能力,以满足较高的制热要求;
房屋朝向与制冷量参考如下:
明明白白选购适合匹数的空调
明白了匹数、制冷、制热等关系,我们在选购空调的时候,可以根据室内的面积来选择空调的匹数大小,参考如下(大约值):[……]

READ MORE

「Electrical-Engineering-and-Automation」- 杂记、技巧

木头上拧螺丝开裂怎么办?
木头上拧螺丝容易开裂?今天才知道用这2个方法轻松解决,涨知识
把螺丝的前端尖尖的部分用钳子夹掉,使螺丝形成平头而不是尖头,这样即使怎么钉木板都不会开裂了。
或者,我们们会先用电钻钻孔(孔径小于螺丝直径),然后再拧入螺丝;
或者,先剪去螺丝头部的尖端(少量即可),然后在拧入。我们猜测其原理类似用电钻钻孔:拧入螺丝时,参差的螺丝前端将内部木质捣碎,沿螺纹排出,以减小内部压力从而防止木头开裂;
或者,将螺丝用水弄湿,再拧入木板中,在拧入螺丝的 1/3 之后,再拧出沾水重新拧入 —— 我们未试过这种方法,只是听说过;[……]

READ MORE

「K4NZ」- 待办事项

papers-we-love/papers-we-love: Papers from the computer science community to read and discuss.
英语
其他事项
# 在Linux中设置显卡及相关内容
# 与KVM有关的CPU设置
# 设置WebDAV、CalDAV服务器
# Glype 项目
# /etc/sysctl.conf介绍;
# java命令介绍
# make教程
# sslsniff
# 性能分析 http://www.brendangregg.com/linuxperf.html http://www.kuqin.com/shuoit/20140910/342080.html
# 虚拟机检测 http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece763104687270e54f7216b818b5e68d4e419ce3b46001d3ba6fd7d62475785d27c1043f50b4beb847065367523b490c38c41c9fecf6879873042720bf14a05a21fb8bc4632c050872a99b86d94adf14284dea3c4a82544ba53120d80e78a2a1764bb7880652692d58e3c124811cafa4161e828043eee5457c243&p=c272c45385cc43e008e2947d074981&newp=91769a47cd934eaf5be78834115c95231610db2151d4d61f64&user=baidu&fm=sc&query=%D0%E9%C4%E2%BB%FA%BC%EC%B2%E2%BC%BC%CA%F5%C6%CA%CE%F6&qid=b9dbb5a600016864&p1=1
# 《working with unix processes》
# Programming in Haskell
# 树莓派 魔镜: http://shumeipai.nxez.com/2015/04/08/make-magic-mirror-with-raspberry-pi.html http://tieba.baidu.com/p/4326191804
# 树莓派集群
配置snort入侵检测
修改风扇的转速
系统级Shadowsocks代理。Shadowsocks:美国云主机,VPS,HHVPS,国外云主机购买、SS搭建。
大海捞针,[……]

READ MORE

「Linux」- 性能优化(学习路径)

背景知识准备
对于性能优化,需要学习以下内容: 1)基础知识:熟练掌握计算机原理、操作系统知识、计算机网络等等知识,熟记于心; 2)排查工具:常用性能工具使用、查看性能指标、定位性能问题; 3)经验总结:总具体的案例中总结经验,抽象出性能排查的一般思路与模式;
熟练掌握”基础原理知识“只是性能优化的开始,这些基础知识盘根错节,任何地方都可能导致性能问题。所以,并不是说掌握基础支持就等于掌握性能问题的排查方法;
性能优化学习
该部分笔记开始于 Linux 性能优化实战 的学习笔记,然后不断整理性能优化相关的内容;
CPU 性能篇 (13 讲)
02 | 基础篇:到底应该怎么理解“平均负载”? => Load Average
03 | 基础篇:经常说的 CPU 上下文切换是什么意思?(上) => Context switch 04 | 基础篇:经常说的 CPU 上下文切换是什么意思?(下)
05 | 基础篇:某个应用的 CPU 使用率居然达到 100%,我该怎么办? => CPU utilization
06 | 案例篇:系统的 CPU 使用率很高,但为啥却找不到高 CPU 的应用? 07 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(上) => Linux process states 08 | 案例篇:系统中出现大量不可中断进程和僵尸进程怎么办?(下)
09 | 基础篇:怎么理解 Linux 软中断? => interrupts and softirqs
10 | 案例篇:系统的软中断 CPU 使用率升高,我该怎么办?
11 | 套路篇:如何迅速分析出系统 CPU 的瓶颈在哪里? => 01.CPU 12 | 套路篇:CPU 性能优化的几个思路
13 | 答疑(一):无法模拟出 RES 中断的问题,怎么办? 14 | 答疑(二):如何用 perf 工具分析 Java 程序?
内存性能篇 (8 讲)
15 | 基础篇:Linux 内存是怎么工作的? 16 | 基础篇:怎么理解内存中的 Buffer 和 Cache? 17 | 案例篇:如何利用系统缓存优化程序的运行效率? 18 | 案例篇:内存泄漏了,我该如何定位和处理? 19 | 案例篇:为什么系统的 Swap 变高了(上) 20 | 案例篇:为什么系统的 Swap 变高了?(下) 21 | 套路篇:如何“快准狠”找到系统内存的问题?
22 | 答疑(三):文件系统与磁盘的区别是什么?
I/O 性能篇 (10 讲)
23 | 基础篇:Linux 文件系统是怎么工作的? 24 | 基础篇:Linux 磁盘 I/O 是怎么工作的(上) 25[……]

READ MORE

「LINUX-PERFORMANCE-TUNING」- I/O

指标(Metrics)

注意事项: 1)注意具体场景,读写类型(顺序还是随机)、读写比例、读写大小、存储类型(有无 RAID 以及 RAID 级别、本地存储还是网络存储)等 2)不同场景的 I/O 性能指标,不能直接进行分析对比
工具(Tools)
df => 文件系统数据的空间容量 / 查看索引节点的容量
/proc/meminfo、/proc/slabinfo / slabtop => 页缓存、目录项缓存、索引节点缓存、具体文件系统的缓存
iostat => 磁盘的 I/O 使用率、吞吐量、响应时间、IOPS
pidstat => 观察到进程的 I/O 吞吐量、块设备 I/O 的延迟
strace / lsof => 进程正在读写的文件、系统调用
filetop / opensnoop => 从内核中跟踪系统调用
联系(Metrics <=> Tools)
磁盘 I/O 查看
iostat iotop
从指标出发
文件系统空间容量、使用量以及剩余空间 => df
索引节点容量、使用量以及剩余量 => df
页缓存和可回收 Slab 缓存 /proc/meminfo sar -r、vmstat
缓冲区 /proc/meminfo sar -r、vmstat
目录项、索引节点以及文件系统的缓存 /proc/slabinfo slabtop 更直观
磁盘 /O 使用率、IOPS、吞吐量、响应时间、I/O 平均大小以及等待队列长度 iostat -d -x sar -d dstat
进程 I/O 大小以及 I/O 延迟 pidstat -d iotop
块设备 I/0 事件跟踪 blktrace => blktrace -d /dev/sda -O – | blkparse -i –
进程 I/O 系统调用跟踪(通过系统调用跟踪进程的 /0) strace
进程块设备 I/O 大小跟踪(安装 bcc 软件) biosnoop biotop
从工具出发
iostat => 磁盘 I/O 使用率、IOPS、 吞吐量、响应时间、I/O 平均大小以及等待队列长度
pidstat => 进程 I/O 大小以及 I/O 延迟
sar => 磁盘 I/O 使用率、IOPS、吞吐量以及响应时间
dstat => 磁盘 I/O 使用率、IOPS 以及吞吐量
iotop => 按 I/O 大小对进程排序
/proc/slabinfo / slabtop => 目录项[……]

READ MORE

「Linux」- 文件系统调优

检查磁盘空间

// 查看文件系统的磁盘空间使用情况(总空间用 1K-blocks 的数量来表示)

$ df /dev/sda1
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda1 30308240 3167020 27124836 11% /

// 通过 -h 选项,以获得更好的可读性

$ df -h /dev/sda1
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 29G 3.1G 26G 11% /

检查索引节点

// 检查 索引节点 的使用情况

$ df -i /dev/sda1
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda1 3870720 157460 3713260 5% /

检查 inode/dentry 缓存
Linux Kernel 使用 Slab 机制,管理 dentry 和 inode 的缓存;
/proc/meminfo 仅显示 Slab 的整体大小,具体到每一种 Slab 缓存,还要查看 /proc/slabinfo 文件;
slabtop
/proc/slabinfo 并不易阅读,在实际性能分析中,我们更常使用 slabtop ,来找到占用内存最多的缓存类型;

# slabtop
Active / Total Objects (% used) : 1448105 / 1884228 (76.9%)
Active / Total Slabs (% used) : 56703 / 56703 (100.0%)
Active / Total Caches (% used) : 113 / 158 (71.5%)
Active / Total Size (% used) : 361280.20K / 669058.59K (54.0%)
Minimum / Average / Maximum Object : 0.01K / 0.35K / 9.62K

OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME
316050 62089 19% 1.06K 10535 30 337120K nfs_inode_cache
216239 206662 95% 0.20K 11[……]

READ MORE

「Linux」- 磁盘 I/O(学习笔记)

解决方案
存储系统的 I/O ,通常是整个系统中最慢的一环。所以, Linux 通过多种缓存机制来优化 I/O 效率: 1)比方说,为了优化文件访问的性能,会使用页缓存、索引节点缓存、目录项缓存等多种缓存机制,以减少对下层块设备的直接调用; 2)为了优化块设备的访问效率,会使用缓冲区,来缓存块设备的数据
磁盘性能指标(常见指标)
不要孤立地去比较某一指标,而要结合读写比例、I/O 类型(随机还是连续)以及 I/O 的大小综合来分析; 1)在数据库、大量小文件等这类随机读写比较多的场景中,IOPS 更能反映系统的整体性能; 2)而在多媒体等顺序读写较多的场景中,吞吐量才更能反映系统的整体性能;
Bandwidth(吞吐量)
指每秒的 I/O 请求大小
Latency(响应时间)
指 I/O 请求从发出到收到响应的间隔时间
IOPS(每秒请求数)
指每秒的 I/O 请求数量
使用率
指磁盘处理 I/O 的时间百分比。过高的使用率(比如超过 80%),通常意味着磁盘 I/O 存在性能瓶颈;
注意,使用率只考虑有没有 I/O,而不考虑 I/O 的大小。换句话说,当使用率是 100% 的时候,磁盘依然有可能接受新的 I/O 请求;
饱和度(Saturation Level)
指磁盘处理 I/O 的繁忙程度;
过高的饱和度,意味着磁盘存在严重的性能瓶颈。当饱和度为 100% 时,磁盘无法接受新的 I/O 请求;
磁盘 I/O 性能(基准测试)
推荐用性能测试工具 fio ,来测试磁盘的 IOPS、吞吐量以及响应时间等核心指标。但还是那句话,因地制宜,灵活选取。在基准测试时,一定要注意根据应用程序 I/O 的特点,来具体评估指标;
并且需要我们测试出,不同 I/O 大小(一般是 512B 至 1MB 中间的若干值)分别在随机读、顺序读、随机写、顺序写等各种场景下的性能情况;
用性能工具得到的这些指标,可以作为后续分析应用程序性能的依据。一旦发生性能问题,你就可以把它们作为磁盘性能的极限值,进而评估磁盘 I/O 的使用情况;
磁盘 I/O 观测
容易被误读的 iostat | Linux Performance 深入理解 iostat
iostat,来自 /proc/diskstats 文件,而 /proc/diskstats 并不提供存储设备性能的数据。其显示的数据包含在队列中等待的时间,所以并不能直接反馈存储设备性能;

# iostat -d -x 1 // -d -x 表示显示所有磁盘 I/[……]

READ MORE

「LINUX-PERFORMANCE-TUNING」- 高延迟

问题描述

# docker run –name=app-iodelay -p 10000:80 -itd feisky/word-pop

# curl http://10.10.50.188:10000/ // 确认案例正常启动
hello world

# curl http://10.10.50.188:10000/popularity/word // 访问示例应用
// 我们发现这个接口居然长时间都没响应

# df // 查看一下文件系统的使用情况

// 这么简单的命令,居然也要等好久才有输出

// 运行如下命令,以制造负载,用于问题排查

# while true; do time curl http://10.10.50.188:10000/popularity/word; sleep 1; done

原因分析
第一步、查看总体情况:top

# top
top – 10:49:54 up 57 days, 1:06, 1 user, load average: 4.26, 1.50, 0.88
Tasks: 191 total, 1 running, 190 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.3 us, 1.0 sy, 0.0 ni, 36.5 id, 62.1 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 1.3 us, 2.3 sy, 0.0 ni, 0.7 id, 95.4 wa, 0.0 hi, 0.3 si, 0.0 st
%Cpu2 : 2.3 us, 5.0 sy, 0.0 ni, 3.7 id, 89.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 0.3 us, 1.7 sy, 0.0 ni, 0.0 id, 98.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 11854.82+total, 117.410 free, 1456.715 used, 10280.70+buff/cache
MiB Swap: 0.000 total, 0.000 free, 0.000 used. 9987.316 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND[……]

READ MORE

「LINUX-PERFORMANCE-TUNING」- 高负载

问题描述
我们运行如下程序,但是我们发现系统负载快速升高,需要进行问题排查;

# docker run -v /tmp:/tmp –name=app-log -itd feisky/logapp // 运行应用程序

# ps -ef | grep /app.py // 确认案例应用正常启动
root 23054 23036 45 08:30 pts/0 00:00:02 python /app.py
root 23089 20643 0 08:30 pts/0 00:00:00 grep –color=auto /app.py

原因分析
第一步、观察总体情况:top

# top
top – 08:32:22 up 56 days, 22:49, 1 user, load average: 3.57, 1.70, 0.89
Tasks: 196 total, 2 running, 194 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.7 us, 1.3 sy, 0.0 ni, 0.0 id, 97.7 wa, 0.0 hi, 0.3 si, 0.0 st
%Cpu1 : 17.9 us, 78.8 sy, 0.0 ni, 3.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 1.0 us, 0.3 sy, 0.0 ni, 97.0 id, 1.7 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 2.0 us, 0.3 sy, 0.0 ni, 97.3 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
MiB Mem : 11854.82+total, 1368.898 free, 1653.500 used, 8832.430 buff/cache
MiB Swap: 0.000 total, 0.000 free, 0.000 used. 9793.617 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
23054 root 20 0 1040092 644228 3304 R 96.7 5.3 1:25.50 python /app.py
7294 apache 20 0 369372 30468 4136 S 2.0[……]

READ MORE

「mysql slowquery」- 由数据库慢查询引发的 I/O 问题

配置环境,以创建负载场景

# git clone https://github.com/feiskyer/linux-perf-examples
# cd linux-perf-examples/mysql-slow

# make run // 启动与案例相关的容器

# docker ps // 确认三个容器都处在运行

// MySQL 需要做一些初始化工作,需要花费几分钟时间

# docker logs -f mysql // 查看 MySQL 的启动过程

// 执行下面的命令,确认它也已经正常运行

# curl http://127.0.0.1:10000/
Index Page

// 初始化数据库,并插入 10000 条商品信息

# make init

// 访问一下商品搜索的接口

# curl http://10.10.50.188/products/geektime

// 这个接口返回的是空数据,而且处理时间超过 15 秒

// 继续执行下面的命令,制造负载以进行测试

# while true; do curl http://192.168.0.10:10000/products/geektime; sleep 5; done

第一步、运行 top 命令,观察资源使用情况

# top
top – 12:02:15 up 6 days, 8:05, 1 user, load average: 0.66, 0.72, 0.59
Tasks: 137 total, 1 running, 81 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.7 us, 1.3 sy, 0.0 ni, 35.9 id, 62.1 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.3 us, 0.7 sy, 0.0 ni, 84.7 id, 14.3 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 8169300 total, 7238472 free, 546132 used, 384696 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 7316952 avail Mem

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27458 999 20 0 833852 57968 13176 S 1.7 0.7 0:12.40 mysqld
27617 r[……]

READ MORE

「redis」- 由于 Redis 错误配置导致的 I/O 压力

配置环境,以创建负载场景

# docker run –name=redis -itd -p 10000:80 feisky/redis-server

# docker run –name=app –network=container:redis -itd feisky/redis-app

# docker ps // 确认两个容器都处于运行状态

# curl http://10.10.50.188:10000/ // 检测应用正常启动
hello redis

// 初始化 Redis 缓存,并且插入 5000 条缓存信息

curl http://10.10.50.188:10000/init/5000
{“elapsed_seconds”:30.26814079284668,”keys_initialized”:5000}

// 测试接口调用

# curl http://10.10.50.188:10000/get_cache
{“count”:1677,”data”:[“d97662fa-06ac-11e9-92c7-0242ac110002″,…],”elapsed_seconds”:10.545469760894775,”type”:”good”}

// 接口调用响应时间较长,需要花费 10 秒

// 循环执行命令,以创造负载,用于调试

# while true; do curl http://10.10.50.188:10000/get_cache; done

第一步、运行 top 命令,观察资源使用情况

# top
top – 12:46:18 up 11 days, 8:49, 1 user, load average: 1.36, 1.36, 1.04
Tasks: 137 total, 1 running, 79 sleeping, 0 stopped, 0 zombie
%Cpu0 : 6.0 us, 2.7 sy, 0.0 ni, 5.7 id, 84.7 wa, 0.0 hi, 1.0 si, 0.0 st
%Cpu1 : 1.0 us, 3.0 sy, 0.0 ni, 94.7 id, 0.0 wa, 0.0 hi, 1.3 si, 0.0 st
KiB Mem : 8169300 total, 7342244 free, 432912 used, 394144 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 7478748 avail Mem

PID USER PR NI VIRT RES[……]

READ MORE

「Linux」- eBPF

bcc:

# for Ubuntu 20.04 LTS
apt-get install bpfcc-tools[……]

READ MORE

「Docker」- Containerd did not exist sucessfully

问题描述
机器关机,再次启动之后,产生如下错误:

Jul 30 13:26:43 localhost.localdomain dockerd[3957]: time=”2018-07-30T13:26:43.932115371+02:00″ level=error msg=”containerd did not exit successfully” error=”exit status 2″ module=libcontainerd

问题原因
不知道……内核版本不满足要求可能导致该问题,但是我的内核版本已经满足要求。
解决办法
重新安装:yum reinstall
相关链接
Docker-CE cannot run because of dockered error: “Containerd did not exist sucessfully” Exist status code 2 #377 Failed to connect to containerd: failed to dial #274 Just installed: Failed to connect to containerd #218[……]

READ MORE

「Docker」- 进程被意外杀死(KILL/9)

问题描述
运行在主机中的 dockerd(docker.service)会收到 KILL/9 信号,便退出。
我们们希望知道是哪个进程发送了 KILL 信号。
该笔记将记录:如何定位发送 KILL 信号的进程
解决方法
使用 Audit 或者 SystemTap 进行捕获。由于 SystemTap 比较复杂,我们这里介绍使用 Audit 的方法。
方法一、使用 Audit 捕获信号
第一步、进行 Audit 配置

apt-get install auditd
auditctl -a exit,always -F arch=b64 -S kill -k audit_kill

# 默认配置已处理日志轮转

第二步、等待 KILL 信号出现……
第三步、通常日志较多,在捕获后,建议尽快结束:

systemctl restart auditd.service

参考文献
How to find Which Process Is Killing mysqld With SIGKILL or SIGTERM on Linux – The Geek Diary SystemTap – Debian Wiki[……]

READ MORE

「Docker」- …dial unix /var/run/docker.sock: connect: permission denied…

问题描述
当使用非 ROOT 用户执行 docker 命令时,
产生如下错误信息:

# docker inspect -f . node:14-alpine
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.40/containers/node:14-alpine/json: dial unix /var/run/docker.sock: connect: permission denied

或者如下错误信息:

Post http:///var/run/docker.sock/v1.19/auth: dial unix /var/run/docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?

问题原因
这些都是同类问题,即非 Root 用户管理 Docker 服务时权限不足。
在 Docker 进程运行时,使用 Unix socket 文件,它由 root:root 所有,所以只有 root 能访问。
如果非 root 用户想要管理,则需要使用 sudo 命令,或者使用其他方法(见下文)。
解决办法

# groupadd docker
# usermod -aG docker “target user”
# systemctl restart docker.service

注意事项
使用 docker 组所授予的权限等同于 root 用户。对系统安全的影响,参考 Docker daemon attack surface 文档
参考文献
Manage Docker as a non-root user[……]

READ MORE

「Docker」- runtime/cgo: pthread_create failed: No space left on device

问题描述
在执行 docker ps 命令时(运行容器、其他命令),产生如下错误:

# docker ps
runtime/cgo: pthread_create failed: No space left on device
SIGABRT: abort
PC=0x7f1a69cace97 m=0 sigcode=18446744073709551610

goroutine 0 [idle]:
runtime: unknown pc 0x7f1a69cace97
stack: frame={sp:0x7ffd418bd5d0, fp:0x0} stack=[0x7ffd410bec10,0x7ffd418bdc50)
00007ffd418bd4d0: 0000000000000000 0000000000000000

00007ffd418bd540: 000000006e43a318 00005601a65818ac
00007ffd418bd550: 0000000000000000 00005601a508d93e <runtime.callCgoMmap+62>
00007ffd418bd560: 00007ffd418bd568 0000000000000000
00007ffd418bd570: 0000000000000000 00007ffd418bd5b8
00007ffd418bd580: 00005601a50855ba <runtime.mmap.func1+90> 0000000000000000
00007ffd418bd590: 0000000000210800 0000002200000003
00007ffd418bd5a0: 00000000ffffffff 00007f1a67a5d000
00007ffd418bd5b0: 00007ffd418bd5f8 00007ffd418bd630
00007ffd418bd5c0: 00005601a5032113 <runtime.mmap+179> 00007ffd418bd600
00007ffd418bd5d0: <0000000000000000 00007ffd418bd628

00007ffd418bd600: 000000006e43a318 00005601a65818ac
00007ffd418bd610: 0000000000210800 00005601a508d93e <runtime.callCgoMmap+62>
00007ffd418bd620: 00007ffd418bd628 00007ffd[……]

READ MORE

「Docker Compose」- 容器编排

Compose,一个用于定义和运行多个容器的工具;
首先,使用 YAML 文件定义一组要启动的容器,然后通过一个简单的命令来启动所有在配置文件中定义的服务;
使用 Docker Compose 部署应用:
(1)创建 Compse 文件。该文件的内容「类似于把docker run的参数写在文件中」;

web:
image: jam01/compseapp
command: python app.py
ports:
– “5000:5000”
volumns:
– .:/composeapp
links:
– redis
redis:
images: redis

也可以用于构建一个镜像:

web:
build: /home/jams/composeapp

关于该 YAML 文件的完整指令列表,可以参考「Overview of Docker Compose」手册;
(2)运行 Compse 程序

#!/bin/sh

# 使用 docker-compose up 来启动这些服务
docker-compose up
# 必须在 docker-compose.yaml 目录中执行大多数的 Compose 命令;

# 为了保证服务的唯一,Compose 将目录名字作为前缀,并使用数字作为后缀,组合起来作为服务名

# 使用-d 选项以守护进程的方式运行。不使用该选项是可以通过 Ctrl+C 来结束;
docker-compose up -d

# 和 docker 命令类似,Compose 也受 DOCKER_HOST 环境变量的影响;

参考文献
GitHub/Docker Compose[……]

READ MORE