docker info 之cgroupdriver和runc

关于cgroupdriver:

docker 默认的cgroupdriver为cgroupfs,也可以手动指定(通过环境变量、命令行参数、daemon.json)systemd,有些docker的rpm包会在 /usr/lib/systemd/system/docker.service 中通过命令行的方式指定cgroupdriver为systemd, 当前支持的cgroupdriver有: cgroupfs、systemd; 命令行设置方式:

虽然创建容器时没有指定cgroupdriver的选项,但是通过修改cgroupdriver重启daemon,可以使得同一个daemon下的容器使用不同的cgroupdriver的(仅仅是出于理解技术实现的思考,实践中似乎没有任何必要)

至于容器使用的native.cgroupdrive 是cgroupfs 还是 systemd 不是配置在容器上的,而是取决于dockerd启动时的配置,如果dockerd配置的是cgroupfs,则容器启动的时候就是使用的cgroupfs,如果dockerd在配置为cgroupfs时已经启动了几个容器,然后修改配置为systemd,则现在启动的容器就是systemd的了,这时候,两种类型的cgroupdriver的容器是并存的,切换cgroupdriver只需要修改dockerd配置后重启容器即可

曾经有文章中疑惑,有的docker容器的cgroup都是在相同的docker目录下的,有的却是docker-xxxx.scope; 原因就在于前者是通过cgroupfs来实现的,后者是通过systemd来实现的; 另外 docker daemon也可以通过选项–cgroup-parent 来指定一个父cgroup(cgroup是有层级结构的),默认为docker,根据cgroupdriver的不同,该cgroup-parent的表现形式也不同,cgroupfs中表现为父目录,systemd中表现为前缀(参考: https://docs.docker.com/engine/reference/commandline/dockerd/#default-cgroup-parent );每个容器都可以有自己的–cgroup-parent,这个对于不同容器进行分组时似乎是不错的。

 

关于runc:

默认runc为 docker-runc,其实runc表现为一个可执行的二进制文件,docker info中显示的只是一个配置时指定的名字,至于该名字对应哪个二进制文件,是在配置的时候指定的,也就是说,你可以在不修改配置的情况下,直接修改对应的二进制文件来修改runc,重启容器就会生效; 另外,创建容器的时候,可以指定runc,指定的是配置daemon时使用的名字,每个容器可以有不同的runc

 

 

磁盘调度算法

参考: http://blog.csdn.net/theorytree/article/details/6259104

说明: 显示所有支持的调度策略, 方框内的是当前启用的调度策略

查看当前系统支持的调度算法:

难道调度算法和设备本身也有关系?从下面来看,阿里云的云盘不支持任何调度策略:

但是:

值得一提的是,Anticipatory算法从Linux 2.6.33版本后,就被移除了,因为CFQ通过配置也能达到Anticipatory算法的效果。

 

查资料发现, 调度策略为 ‘none’ 的现象和阿里云虚拟机没关系,和阿里云云盘没关系,和操作系统版本也没有(直接)关系,仅仅和内核版本有关系, linux内核从3.13开始引入 blk-mq 队列机制,并在3.16得以全部实现,上面看到的非‘none’的情况,内核版本都在3.10之前,为‘none’的情况是被我手动升级内核到4.4.61 的

如何验证是否启用了blk-mq机制?可以通过查看是否存在mq目录,如下:

目录不存在,说明没有启用该机制

存在mq目录,说明使用的是blk-mq机制

参考: https://www.thomas-krenn.com/en/wiki/Linux_Multi-Queue_Block_IO_Queueing_Mechanism_(blk-mq)

参考: http://www.cnblogs.com/cobbliu/p/5389556.html

块儿设备操作

centos中有rpm包util-linux,包含 blockdev命令(其实很多常用的命令都在这里),常见功能如下:

查看预读大小:(单位为扇区)

设置预读大小:

查询是否为只读:( 1 为只读 )

设置设备为只读:

设置设备为读写:

查看扇区大小: (一般都是512)

查看设备容量: (单位为 扇区 )

查看块儿大小: (单位为字节)

查看块儿设备综合信息:

其中:
RO: 是否只读
RA(read ahead):预读扇区数
SSZ(sector size): 扇区大小
BSZ(block size): 块儿大小

 

注意: 这里关于设备的设置在设备重新挂载后会失效,需要重新设置

 

参看: http://www.cnblogs.com/kerrycode/p/4743015.html

java core 调试

根据java core文件打印java堆栈信息:

 

java 之遗失的libjli.so

java 都用了N长时间了,突然,意外地发现有一个依赖的so文件从来没找见过

其实这个so文件在java的安装包中是有的,只是没有添加了ld_path 里面,解决办法:

然后,将/usr/java/jdk1.8.0_45/jre/lib/amd64/jli/  或 /usr/java/jdk1.8.0_45/lib/amd64/jli/ 添加到文件: /etc/ld.so.conf 中,然后执行ldconfig 即可

 

最后,libjli.so 是个啥玩意儿,为啥从来没找见过,却也从来没报错过?

制作openvswitch rpm包

openvswitch已经提供了rpm包的spec文件,所以制作openvswitch rpm包非常容易:

  1. 下载需要的源文件tar包
    http://openvswitch.org/releases/openvswitch-2.7.0.tar.gz
  2. 安装rpm-build
  3. 构建build环境(这里只创建了源码目录)
  4. 将源码包放入源码目录
  5. 从tar包中提取spec文件 (理论上rpmbuild -tb  openvswitch-2.7.0.tar.gz  可以自动搜索spec文件的,但是,该tar包中有多个spec文件,搜索到的未必是我们想使用的)
  6. 制作rpm包 (注意: 提示需要安装啥就先安装啥)

    make其实还是比较快的,主要是test过程长的要命

openvswitch 入门

openvswitch 安装,参考: https://phpor.net/blog/post/5102

启动相关进程:

创建数据库:

语法说明: ovsdb-tool [options] create [db [schema]]

默认数据库位置: /etc/openvswitch/conf.db

默认的表结构: /usr/share/openvswitch/vswitch.ovsschema   (schema 是一个很大的json)

 

启动ovsdb-server:

语法说明: ovsdb-server [database]…  [–remote=remote]…  [–run=command] –log-file[=/var/log/openvswitch/ovsdb-server.log]

默认数据库文件: /etc/openvswitch/conf.db

监听socket文件: 通过 –remote指定,可以是ip:port ,没有默认值

日志文件: 通过–log-file 开启日志,通过 –log-file=/var/log/ovsdb-server.log 来指定文件位置,默认位置: /var/log/openvswitch/ovsdb-server.log

 

通过ovsdb-client 操作数据库

ovsdb-client – command-line interface to ovsdb-server

默认的server socket文件: unix:/var/run/openvswitch/db.sock

 

加载openvswitch 内核模块:

如果不加载该模块,则ovs-vswitchd启动时会报错

该模块内核中已经有了,加载即可:

 

启动ovs-vswitchd:   ovs-vswitchd – Open vSwitch daemon

语法说明: ovs-vswitchd [database]

database 就是ovsdb-server listen的unix socket或ip:port ,这里默认位置为:  unix:/var/run/openvswitch/db.sock

日志通过 –log-file 打开,默认位置: /var/log/openvswitch/ovs-vswitchd.log

 

查看网络配置:

ovs-vsctl 通过

 

各组件之间的关系:

数据库文件是静态文件,如同sqlitedb,需要通过工具(ovsdb-tool)创建;对于mysql数据库,本身就可以直接提供网络服务,但是这里的数据库文件却仅仅是个文件,需要 ovsdb-server 来提供网络服务,ovsdb-server 只知道如何操作数据库(表),对网络却一无所知,但是ovs-vswitchd却是懂网络的,ovs-vswitchd 通过ovsdb-server数据库的变更,执行网络配置,提供一个配置网络的服务;ovs-vsctl 通过ovsdb-server (/var/run/openvswitch/db.sock)操作数据库

 

iptables 之 表、链

iptables中,target/jump决定了符合条件的包到何处去,语法是–jump target-j target

通过-N参数创建自定义链:

之后将BLOCK链作为jump的目标:

如下:

这样从INPUT链中匹配规则6的包都会跳入BLOCK链中,若到达了BLOCK链的结尾(即未被链中的规则匹配),则会回到INPUT链的下一条规则。如果在子链中被ACCEPT了,则就相当于在父链中被ACCEPT了,那么它不会再经过父链中的其他规则。但要注意这个包能被其他表的链匹配;

我们也发现了Chain BLOCK的引用数量为1,就是说有一个规则跳转到了这个链; -j 不仅仅可以是accept和reject,还可以是chain,正是这个才让自定义的chain生效的

为BLOCK链增加规则:

查看如下:

 

 

参考:

http://man.chinaunix.net/network/iptables-tutorial-cn-1.1.19.html    good

http://blog.csdn.net/yu_xiang/article/details/9218589    good

http://arster.blog.51cto.com/714732/908486     good