文章归档

zookeeper原理和实现

zookeeper比较重要的几篇论文:

  1. ZooKeeper’s atomic broadcast protocol: Theory and practice
  2. Zab: High-performance broadcast for primary-backup systems
  3. ZooKeeper: Wait-free coordination for Internet-scale systems
  4. 官方资料:http://zookeeper.apache.org/doc/trunk/

»» 继续阅读全文

Net::FTP与net_cls端口隔离

最近发现一个问题,部署脚本在下载部署包的时候总是报如下错误:

Can't call method "sockport" on an undefined value at /usr/lib/perl5/5.8.5/Net/FTP.pm line 837.

这个部署脚本是用perl语言写的,通过ftp的方式来下载数据包。经过调试后发现,原来是开启了net_cls子系统并设置端口隔离造成的。因为Net::FTP模块总是默认以主动模式来接受数据,什么是主动模式呢?

FTP有两种使用模式:主动和被动。主动模式要求客户端和服务器端同时打开并且监听一个端口以创建连接。在这种情况下,客户端由于安装了防火墙会产生一些问题。所以,创立了被动模式。被动模式只要求服务器端产生一个监听相应端口的进程,这样就可以绕过客户端安装了防火墙的问题。

Net::FTP在接收数据的时候会使用bind(0)的方式监听一个临时端口,让后把这个端口告诉服务器,服务器会与这个端口创建一个新的连接传输数据。问题在于,这个容器内设置了net_cls.bind_port_range,而端口0并不在这个范围之内,所以导致Net::FTP异常。

大规模分布式系统的设计和部署实践

论文  http://mvdirona.com/jrh/talksAndPapers/JamesRH_Lisa.pdf

这篇论文主要从面向运维友好的角度,思考了大规模分布式系统的设计和部署相关的一些原则和最佳实践。

总体设计原则

We have long believed that 80% of operations issues originate in design and development, so this section on overall service design is the largest and most important.

When systems fail, there is a natural tendency to look first to operations since that is where the problem actually took place. Most operations issues, however, either have their genesis in design and development or are best solved there.

对服务整体设计影响最大的一些运维友好的基本原则如下:

  1. Keep things simple and robust
  2. Design for failure

一些更具体的设计运维友好的服务的最佳实践如下:

    »» 继续阅读全文

freezer在内核2.6.32和3.10的区别

今天看了一下内核3.10的代码,对比之前看过的2.6.32的代码,cgroup里freezer子系统的行为差别还是很大的,主要有2个:

  1. freezer处于冻结状态下进程是否仍然可以attach进来,2.6是不行的,但3.10允许
  2. freeze单个cgroup变成freeze掉cgroup以及它的所有后裔

在2.6内核里,当一个进程尝试加入某个freezer控制组时,内核会检查当前freezer cgroup的状态,如果状态为FROZEN或者FREEZING等,则不允许进程加入。但是在3.10里,这个限制去掉了,不管当前freezer cgroup的状态如何,都允许进程加入。

在接口的实现上,2.6内核只提供了can_attach()函数,3.10只提供了freezer_attach() 函数,正常流程上来说,进程在attach某个cgroup的时候,内核会先调用当前cgroup上所有子系统的can_attach()检查一下,当且仅当所有的子系统can_attach()成功时才允许进程加入当前cgroup,然后内核调用freezer子系统的freezer_attach()接口完成attach工作。

»» 继续阅读全文

Borg: google 集群操作系统

论文地址:http://research.google.com/pubs/pub43438.html

1. Introduction

google服务器集群的管理系统,类似于百度的Matrix,阿里的fuxi,腾讯的台风平台等等,还有开源的mesos

Borg provides three main benefits: it

  1. hides the details of resource management and failure handling so its users can focus on application development instead;
  2. operates with very high reliability and availability, and supports applications that do the same; and
  3. lets us run workloads across tens of thousands of machines effectively.

»» 继续阅读全文

netfilter + cgroup实现容器的带宽隔离

我们知道内核提供了一种机制,我们可以通过编写netfilter内核模块来实现对tcp数据包的处理,iptables的原理亦是如此:

那么,通过这种方案,能否实现进程的带宽控制呢?答案是肯定的。带宽控制的目的就是要隔离不同容器的网络需求,避免一个容器因为占用过多的网络带宽导致另一个容器饿死的现象。

尤其是在线离线混部的情况下,如果离线作业占用了过多的带宽资源,就会影响到在线服务的可用性。

实现方案如下:

  1. 扩展一个cgroup模块,或者实现一个新的cgroup子系统
  2. cgroup子系统在初始化的时候,注册netfilter钩子函数,截获所有的数据包
  3. 网络传输出发钩子函数,找到数据包所在的进程pid,找到pid相应的cgroup控制组,从而得到当前进程所在控制组的网络配额
  4. 使用类似与滑动窗口思想的算法实现带宽的限制

但是需要注意以下几个问题:

软限/硬限/整机阈值

对于每一个数据包,先检查是否到达软限,如果还没达到,则允许数据包通过。否则继续检查是否达到硬限,如果超过了硬限,则丢弃数据包。但是如果超过了软限,但是还没有超过硬限,怎么办?仍然需要判断单击带宽的物理阈值是多少。不能超过整机的网络带宽。

注意一旦超过了整机的阈值带宽,一定要先于网卡之前丢包,因为网卡无法区分此数据包是哪个容器的,超出负载后一律丢包。极端情况下:网卡丢的总是被抢占的一方的带宽资源

但是如果我们在netfilter钩子函数里判断以下当前整机带宽是否打满,提前丢包,就可以避免这种情况。

memory.usage_in_bytes内存只增不减

今天发现了一个问题,似乎memory.usage_in_bytes的内存总是在不停的增加,但很少减少,并不能说不减,只是很少。即使这个cgroup里的进程全kill了,usage_in_bytes依然纹丝不动。

经过分析之后,原因如下,与memory.usage_in_bytes的统计方式有关:

  1. 内核在统计的时候,usage_in_bytes包含进程的命名页 + 匿名页,匿名页通常就是file cache
  2. file cache是谁第一次使用算到谁的头上。
  3. file cache只有在完完全全被释放掉之后才会从usage_in_bytes中减掉,即使第一次使用它的进程早已死亡。

简单来说,就是我(某进程)读文件产生的file cache你(内核)算到我的头上,我退出了你也不清空我的计数,万一这个文件正好又被别的cgroup的进程依赖了,这笔帐还是赖在我的头上。。(内核虽然这么做,但其实是不合理的)

1、charge(计入)

file cache的charge函数是mem_cgroup_cache_charge(),这个函数通常是在文件页第一次被读上来时,内核将其加到file cache中时被调用,贴一个常见的调用栈:

[<ffffffff8116019d>] ? mem_cgroup_cache_charge+0xed/0x130 [<ffffffff8110bdba>] ? add_to_page_cache_locked+0xea/0x160 [<ffffffff8119c232>] mpage_readpages+0x102/0x150 [<ffffffff8120157d>] ext4_readpages+0x1d/0x20 [<ffffffff8110c521>] do_generic_file_read.clone.23+0x271/0x450 [<ffffffff8110d1ba>] generic_file_aio_read+0x1ca/0x240 [<ffffffff81164c82>] do_sync_read+0xd2/0x110 [<ffffffff81165463>] vfs_read+0xc3/0x180 [<ffffffff81165571>] sys_read+0x51/0x90

page cache的维护是独立于进程的,所以即使cgroup里的进程退出后,其所使用的page cache不会马上被释放。

2、uncharge(计出)

file cache的计出函数是 mem_cgroup_uncharge_cache_page(),uncharge主要有三种情况:

  1. 手动触发内核回收file cache时被调用
  2. 文件被删除
  3. 内核主动回收file cache时被调用。

手动触发回收file cache,通过sysctl修改vm.drop_caches的值来实现,调用栈如下:

[<ffffffff81114bae>] __mem_cgroup_uncharge_common+0x1ab/0x1f6 [<ffffffff81114c09>] mem_cgroup_uncharge_cache_page+0x10/0x12 [<ffffffff810e0ad0>] __remove_mapping+0xd0/0xf4 [<ffffffff810e0b0a>]

»» 继续阅读全文

cpu带宽控制

一些资料

  1. https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt
  2. CPU bandwidth control for CFS

cpu带宽控制的原理是在给定周期内(cpu.cfs_period_us)内限制进程组的运行时间(cpu.cfs_quota_us),这两个参数值通过cpu子系统来设置。

cfs_rq相关的两个成员是runtime_remainingruntime_expires,前者是当前进程组的剩余时间片,后者是时间片的到期时间。

内核的做法是:

  1. 每次进程切换的时候更新当前进程的运行时间,检查进程时钟带宽是否超过阈值。
  2. 通过一个定时器,每隔固定的cpu.cfs_period_us周期,更新进程组的时钟带宽

»» 继续阅读全文

扩展net_cls子系统实现端口隔离

端口隔离的目的是要严格隔离不同容器所使用的端口段。我们通过扩展内核net_cls模块来达到此目的

  1. bind端口隔离:限制bind使用的端口范围,通过net_cls.bind_port_range配置文件设置
  2. connect端口隔离:限制进程能connect的端口范围,通过net_cls.connect_port_range配置文件设置

其中bind_port_range和connect_port_range配置文件的接口定义如下:

static struct cftype ss_files[] = {   {     .name = "bind_port_range",     .read_seq_string = port_range_read,     .write_string = port_range_write,     .max_write_len = 20U,     .private = FILE_BIND,   },   {     .name = "connect_port_range",     .read_seq_string = port_range_read,     .write_string = port_range_write,     .max_write_len = 20U,     .private = FILE_CONNECT,   },   //... }

通过port_range_read/port_range_write函数来实现配置参数的读写。我们重点关注cgrp_local_port_range()函数,这个函数取得当前进程所在的cgroup能使用的端口范围段,区分于是否是bind/connect:

/** * cgrp_local_port_range - get available local port range * * @connect: select port range */ int cgrp_local_port_range(int *low, int *high, int connect) {

»» 继续阅读全文

编写可读代码的艺术

可读性的基本定理:代码的写法应当使别人理解它所需的时间最小化

»» 继续阅读全文

第 4 页,共 13 页« 最新...23456...10...最旧 »