文章归档

浅析 Linux 初始化 init 系统

  1. 浅析 Linux 初始化 init 系统,第 1 部分: sysvinit
  2. 浅析 Linux 初始化 init 系统,第 2 部分: UpStart
  3. 浅析 Linux 初始化 init 系统,第 3 部分: Systemd

其中关于systemd对系统启动速度的优化很有趣,另外systemd引入的资源隔离也是一个很值得思考的问题。

基于veth的网络虚拟化

关于Network Namespace的原理不再详解,请直接移步:Namespaces in operation, part 7: Network namespaces 

但是需要注意的,这个文章里network namespace操作所使用的是最新内核&操作系统提供的非常便利的ip netns工具,不过这些工具在低版本的操作系统上都是不提供的。如果真的需要使用network namespace,最好通过netlink编程的方式来实现,直接基于操作系统调用来完成所有设备的虚拟化工作 我们知道在clone进程的时候使用CLONE_NEWNET参数可以创建一个新的独立的network namespace,但是光有这个还是远远不够的,所有网络设备都没有初始化、没启动,这个时候的容器就是一个完全的离线的容器,不在任何网络里,也访问不了任何网络。 

为了让容器独立能够与外网接通,我们需要创建并初始化一些设备,让容器内的网络和外网互通,veth是一种比较简单的方案

»» 继续阅读全文

Namespaces系列3:network namespace

As the name would imply, network namespaces partition the use of the network—devices, addresses, ports, routes, firewall rules, etc.—into separate boxes, essentially virtualizing the network within a single running kernel instance. Network namespaces entered the kernel in 2.6.24

1. 简介

简单点来说,network namespace主要实现了一套独立的协议栈,为不同的应用程序实现完整的网络隔离

由于有了独立的网络协议栈,应用程序可以灵活自主的组建适合自己的网络架构。network namespace技术本身其实不复杂,复杂的是有了network namespace之后网络的构建,就像给你一堆服务器,交换机,路由器,你需要用网线把这些设备连接起来,并设置路由规则,防火墙规则,网络地址等等,才能实现网络访问

network namespace能解决很多问题,常见的如端口

在多个业务混部在同一个机器上的时候,端口协调是一件非常困难的事情,kubernetes在介绍自身的网络模型中也提到了这一点:

Coordinating ports across multiple developers is very difficult to do at scale and exposes users to cluster-level issues outside of their control. Dynamic port allocation brings a lot of complications to the system - every application has to take

»» 继续阅读全文

Namespaces系列2:mnt namespace

mnt namespaces是实现容器文件系统最核心的基础技术之一,mnt namespaces可以为容器提供一个独立的文件系统视图

这里我除了介绍mnt namespace相关技术之外,还介绍shared subtrees技术,which allows mount and unmount events to be propagated between mount namespaces in an automatic, controlled fashion.

1. 简介

mnt namespaces是linux最早引入的namespace,appearing in 2002 in Linux 2.4.19. 主要是为了隔离不同进程组可以看到的挂载点,meaning that processes in different namespaces see and are able to manipulate different views of the single directory hierarchy.

这里面的隔离有几个意思:

  1. 同一个mnt namespace下的所有进程看到的mount points一定是一样的
  2. 不同的mnt namespace下的进程看到的mount points不一定是一样的
  3. 不同的mnt namespace下所做的mount和umount操作,都是互相不可见的

这个不一定的原因是因为mnt namespace刚创建出来的时候,默认会继承父亲namespace的所有信息,但是如上面第三点说的,之后所做的任何mount & umount操作,都与父namespace无关,也和任何其他的namespace无关

操作系统启动的时候,内核会为系统初始化一个根mnt namespace,也叫"initial namespace". 后面的mnt namespace都是通过clone系统调用 + CLONE_NEWNS参数创建出来的,When a new mount namespace is created, it

»» 继续阅读全文

Namespaces系列1:PID namespace

1. 简介

The global resource isolated by PID namespaces is the process ID number space. This means that processes in different PID namespaces can have the same process ID.

As with processes on a traditional Linux (or UNIX) system, the process IDs within a PID namespace are unique, and are assigned sequentially starting with PID 1. Likewise, as on a traditional Linux system, PID 1—the init process—is special: it is the first process created within the namespace, and it performs certain management tasks within the namespace.

PID隔离最主要的两个目的是:

  1. 为容器提供安全的进程操作
  2. »» 继续阅读全文

Intel Cache Allocation Technology: CPU LLC Isolate

LLC是指Last Level cache,目前来说通常也就是L3 Cache,CAT是指Intel架构提供的一组工具&技术,用以支持LLC隔离。隔离的目的是针对Latency sensitive服务程序,提高QoS。可以考虑到两个LS敏感的程序跑在同一个机器上相互影响的程度还是比较大。

相关的一些资料如下:

  1. x86: Intel Cache Allocation Technology support
  2. Intel® 64 and IA-32 Architectures Software Developer Manuals 其中的 17.16 PLATFORM SHARED RESOURCE CONTROL: CACHE ALLOCATION TECHNOLOGY

»» 继续阅读全文

linux内核调度:cfs(Completely Fair Scheduler) 的简单原理

cfs为完全公平调度提供了一种统一的抽象:虚拟时钟vruntime

不关心进程是否sleep,不关心是否为交互式进程,它只基于虚拟时钟,通过一棵RB树维护所有的进程。RB树的key就是进程的虚拟运行时间。

cfs提供了一种可扩展的进程调度架构,实现了机制和策略的分离

因为真实的硬件上同一时刻只能允许一个任务在运行,所以为了模拟并行,需要引入一个虚拟时钟的概念。虚拟时钟将进程睡眠补偿,优先级,权限等各种参数映射到同一维度。

»» 继续阅读全文

memory.force_empty清空cgroup内存

linux-2.6.32.68

memory.force_empty这个参数的最主要作用就是触发cgroup内存回收。但是有两种方式:

  1. root用户通过echo 1 > memory.force_empty 强制回收内存
  2. memory cgroup被删除时,会将当前计数charge到parent cgroup。(可能会触发parent cgroup的内存回收)

对应内核的函数是

/* * make mem_cgroup's charge to be 0 if there is no task. * This enables deleting this mem_cgroup. */ static int mem_cgroup_force_empty(struct mem_cgroup *mem, bool free_all)

这个函数的使用有两个基本的前提条件:

  1. 当前cgroup里不允许有任何进程
  2. 不存在子cgroup

因为mem_cgroup_force_empty()函数的实现里多处使用如下判断:

    if (cgroup_task_count(cgrp) || !list_empty(&cgrp->children))         goto out;

dentry缓存

最近追查某线上服务发现一个问题:频繁的创建&删除目录或者文件,会消耗大量的物理内存。

原因是因为,目录或者文件删除后,dentry并没有立即释放,而是保存在了superblock上的lru链表上。通常只有内核认为内存紧张的时候才会回收此部分内存。

不过由于dentry结构非常小,这种case下内存增长是很慢。

Active / Total Objects (% used) : 740781 / 764463 (96.9%) Active / Total Slabs (% used) : 31522 / 31522 (100.0%) Active / Total Caches (% used) : 74 / 101 (73.3%) Active / Total Size (% used) : 144439.65K / 148432.28K (97.3%) Minimum / Average / Maximum Object : 0.01K / 0.19K / 8.00K OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME 460278 460278 100% 0.19K 21918 21 87672K dentry 91416 81993 89% 0.10K 2344 39 9376K buffer_head 30660 29625 96% 0.19K 1460 21 5840K

»» 继续阅读全文

cpuset子系统与cpu亲缘性设置sched_setaffinity

目前cpu亲缘性设置有两种方式:

  1. 通过sched_setaffinity()函数将进程绑定到某些cpu上运行
  2. 讲进程加入到cpuset控制组,通过修改cpuset.cpus参数来实现亲缘性设置

但是有一点需要注意的是,通过sched_setaffinity设置的cpu_mask不允许超出cpuset.cpus的范围,超出部分是无效的。

举例,进程A所在的cpuset控制组cpuset.cpus参数值是0,1,2,3,4,但是进程运行期间调用sched_setaffinity()修改cpu_mask为0,1,2,4,7。因为7并不在cpuset.cpus范围里,所以内核会把7忽略掉,最终进程只能在0,1,2,4这几个CPU上运行。

»» 继续阅读全文

第 2 页,共 13 页12345...10...最旧 »