如何改变docker image的存放路径

OpenSkill 回复了问题 • 2 人关注 • 1 个回复 • 1627 次浏览 • 2015-09-13 18:09 • 来自相关话题

HDFS高可用方案之QJM

OpenSkill 发表了文章 • 0 个评论 • 860 次浏览 • 2015-09-12 20:18 • 来自相关话题

喜欢一个人,可以为TA做任何事,得到不接受却依然心甘情愿鞍前马后,苦苦等候那一线希望。对,这就是备胎,挂在汽车背后,可能一辈子也用不到的那个圆圈状的玩意儿,大部分情况下,它都会默默地挂在那里,等待几千分之一的机会,有个倒霉的轮子兄弟出事了,于是它就能派上用场了……(摘自豆瓣)
 
在Hadoop的分布式文件系统HDFS中,NameNode用来保存文件系统的元数据(包含目录结构/数据块位置等),如果NameNode上的数据丢失,HDFS上对应的文件数据就无法找回来了。Hadoop在2.0.0之前的版本,使用SecondaryNameNode备份NameNode的数据,但SecondaryNameNode无法转成NameNode,如果NameNode挂了,整个HDFS就会挂掉,无法实现真正的failover。这篇博文总结了5种Hadoop HA(High Available,高可用)方案,Hadoop2之后官方引入了QJM(Quorum Journal Manager)和NFS用于NameNode的备份和切换。本方将介绍的是QJM方案,它使用第二个NameNode实时同步当前NameNode的数据,相比于SecondaryNameNode,他可以随时切换成为真正的NameNode(一个可转正的高级备胎)。
 
先看看没有HA的HDFS的系统架构(用draw.io画的,尼马这么好的网站也被墙了):




然后有HA方案的系统架构:




以下的实验基于4个节点的Hadoop集群。其中每个节点的运行的进程列表如下:




实验环境中,所有节点的运行环境基本相同:
[]Ubuntu14.04 X64[/][]4G内存[/][]OpenJDK-1.7.0[/][]100Mbps以太网[/]
下面是实现这个系统的流程(官方文档+个人注解+辅助Shell命令)。

安装Hadoop系统
严格按照单节点搭建和集群搭建两个步骤,系统建起来完全没压力。我遇到的问题是刚开始在配置文件(salves和core-site.xml等文件)中使用的是ip地址而非主机名,然后在log文件里看到各种无法连接。解决方案是修改主机名并在hosts文件里建立映射关系。hostname {new_hostname} # 修改主机名,只有当前Session有效
sudo vi /etc/hostname # 永久修改主机名的方法另外,对于64位的系统,最好重新编译源码。

修改配置文件
hdfs-site.xml文件:<configuration>
<property>
<name>dfs.namenode.name.dir</name>
<value>/data/hadoop/namenode</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/data/hadoop/datanode</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>hd1:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>hd3:8020</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>hd1:50070</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>hd3:50070</value>
</property>
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hd1:8485;hd2:8485;hd4:8485/mycluster</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hduser/.ssh/id_rsa</value>
</property>
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/data/hadoop/journalnode</value>
</property>
</configuration>
[]其中nameservices是集群的命名空间,即使有多个集群,可以共用配置文件,但是要注意某些配置项的顺序。[/][]dfs.ha.namenodes.mycluster中的mycluster是可以任取的,但是要和dfs.nameservices对应。[/][]dfs.namenode.rpc-address.mycluster.nn1参考上一条。[/][]dfs.namenode.shared.edits.dir值的格式是"qjournal://host1:port1;host2:port2;host3:port3/journalId",用来指定对应的JN节点,journalId建议使用和nameservices相同的名称。[/][]dfs.client.failover.proxy.provider.mycluster指定激活NameNode的Java类,目前Hadoop内置的只有上面那个。[/][]dfs.ha.fencing.methods是来用来隔离失效的NameNode的方法,有sshfence和Shell两种方式。sshfence需要配置dfs.ha.fencing.ssh.private-key-files私钥文件,以便交互的过程不需要输入密码。[/][]dfs.journalnode.edits.dir是JN保存数据的文件。[/]
 
core-site.xml文件:<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
</configuration>
[]注意mycluster要和dhfs-site.xml中的dfs.nameservices对应。fs.defaultFS不用端口号。[/]
 

部署
改好配置文件好,就要将配置文件同步到所有的机器上了。可以用rsync将文件同步到多台机器上。rsync是一个增量同步工具,需要先安装。下面的rsync.sh的功能是将当前目录的所有文件发送到文件或参数对应的机器上。$ cat rsync.sh
#! /bin/bash

dir=`pwd`
pdir=`dirname $dir`

send(){
echo "Sending to $2:$1"
rsync -avez -e ssh $1 $2:$3
}

mul_send(){
while read host
do
send $dir $host $pdir
done < $1
}

[ -f $1 ] && mul_send $1 || send $dir $1 $pdir将rsync.sh放在etc/hadoop目录下,进入目录运行chmod +x rsync.sh
./rsync.sh slaves
# or ./rsync.sh hostname发送完文件之后,就是启动系统。步骤如下:
 
启动JNs.

在所有JournalNode上运行sbin/hadoop-daemon.sh --script hdfs start journalnode启动NameNode.
 
在原NameNode上运行bin/hadoop --script hdfs start namenode # NameNode需要已经format。[url=使用上面的rsync.sh文件]/code[/url]将原NameNode(nn1)上的数据复制到第二个NameNode(nn2)。然后在nn2上运行:[code]bin/hdfs namenode -bootstrapStandby启动其他节点

在NameNode上运行sbin/start-dfs.sh

切换NameNode
手动方式

上面的NameNode默认以standby的状态启动,这时因为没有active的NameNode,所以是不能在HDFS读写文件,需要将其中的一个转成active状态。比如将nn1(对应前面的配置)转成Active:bin/hdfs haadmin -transitionToActive nn1然后在NameNode的web页面上部的括号里的standby变成active。
转成standby的命令是:
bin/hdfs haadmin -transitionToStandby nn1
 
自动切换
在当前NameNode不能使用时自动切换到第二个NameNode上,需要借助于ZooKeeper[url=ZK]/url。

ZK的安装过程和Hadoop差不多,就是下载文件、修改配置、复制到所有机器、启动。具体步骤在这里。

配置文件conf/zoo.conf:tickTime=2000
dataDir=/data/hadoop/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=hd2:2888:3888
server.2=hd3:2888:3888
server.3=hd4:2888:3888hd2,hd3,hd4是主机名,至少需要三台,这个在一台机挂了整个系统还能用,ZK的数量一般是奇数,为什么为奇数可以参考这里。
 
然后要在hdfs-site.xml上添加配置:<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<property>
<name>ha.zookeeper.quorum</name>
<value>hd2:2181,hd3:2181,hd4:2181</value>
</property>然后就是在NameNode的机器上初始化NameNode在ZK的状态了:bin/hdfs zkfc -formatZK重启HDFS或手动启动DFSZKFailoverController(ZKFC):sbin/stop-dfs.sh # 重启hdfs
sbin/start-dfs.sh
sbin/hadoop-daemon.sh start zkfc # 启动ZKFC在该HA方案中,每一个NameNode都有一个对应的ZKFC。ZKFC会随NameNode启动。
 
测试
 
在当前NameNode运行jps看NameNode的进程ID,然后kill掉。通过Web页面( http://hdx:50070 ),可以看到standby的NameNode几乎在kill的同时转成active了。
转载地址:原文地址 查看全部
喜欢一个人,可以为TA做任何事,得到不接受却依然心甘情愿鞍前马后,苦苦等候那一线希望。对,这就是备胎,挂在汽车背后,可能一辈子也用不到的那个圆圈状的玩意儿,大部分情况下,它都会默默地挂在那里,等待几千分之一的机会,有个倒霉的轮子兄弟出事了,于是它就能派上用场了……(摘自豆瓣)
 
在Hadoop的分布式文件系统HDFS中,NameNode用来保存文件系统的元数据(包含目录结构/数据块位置等),如果NameNode上的数据丢失,HDFS上对应的文件数据就无法找回来了。Hadoop在2.0.0之前的版本,使用SecondaryNameNode备份NameNode的数据,但SecondaryNameNode无法转成NameNode,如果NameNode挂了,整个HDFS就会挂掉,无法实现真正的failover。这篇博文总结了5种Hadoop HA(High Available,高可用)方案,Hadoop2之后官方引入了QJM(Quorum Journal Manager)和NFS用于NameNode的备份和切换。本方将介绍的是QJM方案,它使用第二个NameNode实时同步当前NameNode的数据,相比于SecondaryNameNode,他可以随时切换成为真正的NameNode(一个可转正的高级备胎)。
 
先看看没有HA的HDFS的系统架构(用draw.io画的,尼马这么好的网站也被墙了):
hd21.png

然后有HA方案的系统架构:
hd22.png

以下的实验基于4个节点的Hadoop集群。其中每个节点的运行的进程列表如下:
hd23.png

实验环境中,所有节点的运行环境基本相同:
    []Ubuntu14.04 X64[/][]4G内存[/][]OpenJDK-1.7.0[/][]100Mbps以太网[/]

下面是实现这个系统的流程(官方文档+个人注解+辅助Shell命令)。


  1. 安装Hadoop系统


严格按照单节点搭建集群搭建两个步骤,系统建起来完全没压力。我遇到的问题是刚开始在配置文件(salves和core-site.xml等文件)中使用的是ip地址而非主机名,然后在log文件里看到各种无法连接。解决方案是修改主机名并在hosts文件里建立映射关系。
hostname {new_hostname} # 修改主机名,只有当前Session有效
sudo vi /etc/hostname # 永久修改主机名的方法
另外,对于64位的系统,最好重新编译源码。


  1. 修改配置文件


hdfs-site.xml文件:
<configuration>
<property>
<name>dfs.namenode.name.dir</name>
<value>/data/hadoop/namenode</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/data/hadoop/datanode</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>hd1:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>hd3:8020</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn1</name>
<value>hd1:50070</value>
</property>
<property>
<name>dfs.namenode.http-address.mycluster.nn2</name>
<value>hd3:50070</value>
</property>
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://hd1:8485;hd2:8485;hd4:8485/mycluster</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/hduser/.ssh/id_rsa</value>
</property>
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/data/hadoop/journalnode</value>
</property>
</configuration>

    []其中nameservices是集群的命名空间,即使有多个集群,可以共用配置文件,但是要注意某些配置项的顺序。[/][]dfs.ha.namenodes.mycluster中的mycluster是可以任取的,但是要和dfs.nameservices对应。[/][]dfs.namenode.rpc-address.mycluster.nn1参考上一条。[/][]dfs.namenode.shared.edits.dir值的格式是"qjournal://host1:port1;host2:port2;host3:port3/journalId",用来指定对应的JN节点,journalId建议使用和nameservices相同的名称。[/][]dfs.client.failover.proxy.provider.mycluster指定激活NameNode的Java类,目前Hadoop内置的只有上面那个。[/][]dfs.ha.fencing.methods是来用来隔离失效的NameNode的方法,有sshfence和Shell两种方式。sshfence需要配置dfs.ha.fencing.ssh.private-key-files私钥文件,以便交互的过程不需要输入密码。[/][]dfs.journalnode.edits.dir是JN保存数据的文件。[/]

 
core-site.xml文件:
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
</configuration>

    []注意mycluster要和dhfs-site.xml中的dfs.nameservices对应。fs.defaultFS不用端口号。[/]

 


  1. 部署


改好配置文件好,就要将配置文件同步到所有的机器上了。可以用rsync将文件同步到多台机器上。rsync是一个增量同步工具,需要先安装。下面的rsync.sh的功能是将当前目录的所有文件发送到文件或参数对应的机器上。
$ cat rsync.sh 
#! /bin/bash

dir=`pwd`
pdir=`dirname $dir`

send(){
echo "Sending to $2:$1"
rsync -avez -e ssh $1 $2:$3
}

mul_send(){
while read host
do
send $dir $host $pdir
done < $1
}

[ -f $1 ] && mul_send $1 || send $dir $1 $pdir
将rsync.sh放在etc/hadoop目录下,进入目录运行
chmod +x rsync.sh
./rsync.sh slaves
# or ./rsync.sh hostname
发送完文件之后,就是启动系统。步骤如下:
 
启动JNs.

在所有JournalNode上运行
sbin/hadoop-daemon.sh --script hdfs start journalnode
启动NameNode.
 
在原NameNode上运行
bin/hadoop --script hdfs start namenode # NameNode需要已经format。[url=使用上面的rsync.sh文件]/code[/url]将原NameNode(nn1)上的数据复制到第二个NameNode(nn2)。然后在nn2上运行:[code]bin/hdfs namenode -bootstrapStandby
启动其他节点

在NameNode上运行
sbin/start-dfs.sh


  1. 切换NameNode


手动方式

上面的NameNode默认以standby的状态启动,这时因为没有active的NameNode,所以是不能在HDFS读写文件,需要将其中的一个转成active状态。比如将nn1(对应前面的配置)转成Active:
bin/hdfs haadmin -transitionToActive nn1
然后在NameNode的web页面上部的括号里的standby变成active。
转成standby的命令是:
bin/hdfs haadmin -transitionToStandby nn1
 
自动切换
在当前NameNode不能使用时自动切换到第二个NameNode上,需要借助于ZooKeeper[url=ZK]/url

ZK的安装过程和Hadoop差不多,就是下载文件、修改配置、复制到所有机器、启动。具体步骤在这里。

配置文件conf/zoo.conf:
tickTime=2000
dataDir=/data/hadoop/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=hd2:2888:3888
server.2=hd3:2888:3888
server.3=hd4:2888:3888
hd2,hd3,hd4是主机名,至少需要三台,这个在一台机挂了整个系统还能用,ZK的数量一般是奇数,为什么为奇数可以参考这里。
 
然后要在hdfs-site.xml上添加配置:
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<property>
<name>ha.zookeeper.quorum</name>
<value>hd2:2181,hd3:2181,hd4:2181</value>
</property>
然后就是在NameNode的机器上初始化NameNode在ZK的状态了:
bin/hdfs zkfc -formatZK
重启HDFS或手动启动DFSZKFailoverController(ZKFC):
sbin/stop-dfs.sh # 重启hdfs
sbin/start-dfs.sh
sbin/hadoop-daemon.sh start zkfc # 启动ZKFC
在该HA方案中,每一个NameNode都有一个对应的ZKFC。ZKFC会随NameNode启动。
 
测试
 
在当前NameNode运行jps看NameNode的进程ID,然后kill掉。通过Web页面( http://hdx:50070 ),可以看到standby的NameNode几乎在kill的同时转成active了。
转载地址:原文地址

Docker镜像无法删除

采菊篱下 回复了问题 • 2 人关注 • 1 个回复 • 1309 次浏览 • 2015-09-10 11:09 • 来自相关话题

HDFS中Datanode存在大量没有删除的Block磁盘被占满案例分析

OpenSkill 发表了文章 • 0 个评论 • 743 次浏览 • 2015-09-09 00:09 • 来自相关话题

最近发现hdfs中,有的datanode节点,磁盘发生告警,然后分析了一下。
然后上网搜索了一下为什么,分析如下:
 
查看对应datanode的数据目录,发现确实有很多的数据块(量非常大,都超过了实际hdfs中的数据块总量)
 
这时候,猜测应该是有很多需要被删除的数据块没有被删除。猜测可能是NameNode和DataNode之间的通讯出现异常导致。于是查看NameNode和DataNode日志,发现并没有任何异常信息,只是发现NameNode定时对其中的三台机器发出了删除指令BLOCK[i] ask 192.168.200.8:50010 to delete blk_7080908721303033545_7530145 BLOCK[/i] ask 192.168.200.9:50010 to delete blk_-6550808355677895247_7465333 BLOCK* ask 192.168.200.7:50010 to delete blk_2415291932316966347_7460687
按照网上的方法,通过dfsadmin证实了,确实是有大量的block在等待删除hadoop dfsadmin -metasave meta.txt然后到logs目录下查看meta.txt文件结果如下:Metasave: Blocks 572428 waiting deletion from 8 datanodes.显示有几十万的block等待删除
 
没有办法,只好从源码着手。在FSNameSystem.java文件里面找到了最终问题的所在:public int computeDatanodeWork() throws IOException {
int workFound = 0;
int blocksToProcess = 0;
int nodesToProcess = 0;
// blocks should not be replicated or removed if safe mode is on
if (isInSafeMode())
return workFound;
synchronized(heartbeats) {
blocksToProcess = (int)(heartbeats.size()
* ReplicationMonitor.REPLICATION_WORK_MULTIPLIER_PER_ITERATION);
nodesToProcess = (int)Math.ceil((double)heartbeats.size()
* ReplicationMonitor.INVALIDATE_WORK_PCT_PER_ITERATION / 100);

}

workFound = computeReplicationWork(blocksToProcess);

// Update FSNamesystemMetrics counters
synchronized (this) {
pendingReplicationBlocksCount = pendingReplications.size();
underReplicatedBlocksCount = neededReplications.size();
scheduledReplicationBlocksCount = workFound;
corruptReplicaBlocksCount = corruptReplicas.size();
}

workFound += computeInvalidateWork(nodesToProcess);

return workFound;
}computeInvalidateWork就是用于计算这次需要删除的数据块。但是并不是每次都把所有的节点都处理一遍,而是每次只处理nodesToProcess个节点,而这个数量决定于datanode的总数(heartbeats.size,我这儿是8)和一个系数(INVALIDATE_WORK_PCT_PER_ITERATION,写死的32)。
 
也就是说每次只处理

8*32% = 3(这就解释了为啥每次只删除三台数据节点上的数据块。)

再查看节点选择部分:……
private Map<String, Collection<Block>> recentInvalidateSets =
new TreeMap<String, Collection<Block>>();

……
String firstNodeId = recentInvalidateSets.keySet().iterator().next();

……发现是通过iterator遍历的,然后悲剧的发现recentInvalidateSets用的是TreeMap,也就是说是有序的……

所以只要这三个节点有数据需要删除,就不会删除到其他节点
 
这时候,发现这个问题是调整的时候,修改了一个配置项(dfs.replication.interval,默认是3秒,我修改成了30秒)导致的,当时修改的初衷是防止过早出现数据块复制。但是修改这个配置项以后,数据块副本数检查的间隔拉长了,导致30秒内,有几台机器一直有数据块需要删除,从而无法删除其他节点上的数据块,最终导致磁盘空间无法释放。因为INVALIDATE_WORK_PCT_PER_ITERATION是系统写死的,所以只能通过把dfs.replication.interval改回来,暂时解决这个问题。
  查看全部
最近发现hdfs中,有的datanode节点,磁盘发生告警,然后分析了一下。
然后上网搜索了一下为什么,分析如下:
 
查看对应datanode的数据目录,发现确实有很多的数据块(量非常大,都超过了实际hdfs中的数据块总量)
 
这时候,猜测应该是有很多需要被删除的数据块没有被删除。猜测可能是NameNode和DataNode之间的通讯出现异常导致。于是查看NameNode和DataNode日志,发现并没有任何异常信息,只是发现NameNode定时对其中的三台机器发出了删除指令
BLOCK[i] ask 192.168.200.8:50010 to delete  blk_7080908721303033545_7530145 BLOCK[/i] ask 192.168.200.9:50010 to delete  blk_-6550808355677895247_7465333 BLOCK* ask 192.168.200.7:50010 to delete  blk_2415291932316966347_7460687

按照网上的方法,通过dfsadmin证实了,确实是有大量的block在等待删除
hadoop dfsadmin -metasave meta.txt
然后到logs目录下查看meta.txt文件结果如下:
Metasave: Blocks 572428 waiting deletion from 8 datanodes.
显示有几十万的block等待删除
 
没有办法,只好从源码着手。在FSNameSystem.java文件里面找到了最终问题的所在:
public int computeDatanodeWork() throws IOException {
int workFound = 0;
int blocksToProcess = 0;
int nodesToProcess = 0;
// blocks should not be replicated or removed if safe mode is on
if (isInSafeMode())
return workFound;
synchronized(heartbeats) {
blocksToProcess = (int)(heartbeats.size()
* ReplicationMonitor.REPLICATION_WORK_MULTIPLIER_PER_ITERATION);
nodesToProcess = (int)Math.ceil((double)heartbeats.size()
* ReplicationMonitor.INVALIDATE_WORK_PCT_PER_ITERATION / 100);

}

workFound = computeReplicationWork(blocksToProcess);

// Update FSNamesystemMetrics counters
synchronized (this) {
pendingReplicationBlocksCount = pendingReplications.size();
underReplicatedBlocksCount = neededReplications.size();
scheduledReplicationBlocksCount = workFound;
corruptReplicaBlocksCount = corruptReplicas.size();
}

workFound += computeInvalidateWork(nodesToProcess);

return workFound;
}
computeInvalidateWork就是用于计算这次需要删除的数据块。但是并不是每次都把所有的节点都处理一遍,而是每次只处理nodesToProcess个节点,而这个数量决定于datanode的总数(heartbeats.size,我这儿是8)和一个系数(INVALIDATE_WORK_PCT_PER_ITERATION,写死的32)。
 
也就是说每次只处理

8*32% = 3(这就解释了为啥每次只删除三台数据节点上的数据块。)

再查看节点选择部分:
……
private Map<String, Collection<Block>> recentInvalidateSets =
new TreeMap<String, Collection<Block>>();

……
String firstNodeId = recentInvalidateSets.keySet().iterator().next();

……
发现是通过iterator遍历的,然后悲剧的发现recentInvalidateSets用的是TreeMap,也就是说是有序的……

所以只要这三个节点有数据需要删除,就不会删除到其他节点
 
这时候,发现这个问题是调整的时候,修改了一个配置项(dfs.replication.interval,默认是3秒,我修改成了30秒)导致的,当时修改的初衷是防止过早出现数据块复制。但是修改这个配置项以后,数据块副本数检查的间隔拉长了,导致30秒内,有几台机器一直有数据块需要删除,从而无法删除其他节点上的数据块,最终导致磁盘空间无法释放。因为INVALIDATE_WORK_PCT_PER_ITERATION是系统写死的,所以只能通过把dfs.replication.interval改回来,暂时解决这个问题。
 

Docker not support swap limit capabilities

Ansible 回复了问题 • 2 人关注 • 1 个回复 • 2001 次浏览 • 2015-09-07 01:57 • 来自相关话题

运行docker报错Cannot connect to the Docker daemon. Is 'docker -d' running on this host?

Ansible 回复了问题 • 2 人关注 • 1 个回复 • 2095 次浏览 • 2015-09-01 20:53 • 来自相关话题

KVM性能测试报告

Ansible 发表了文章 • 0 个评论 • 2107 次浏览 • 2015-09-01 11:11 • 来自相关话题

本测试试图找出以下问题的答案:
           1. 虚拟机相对于物理机性能损失有多严重(CPU/MEM/NET/DISK) 
           2. 对于多个虚拟机,KVM 对资源的分配是否公正
           3. 找出性能最好的物理机磁盘类型和虚拟机磁盘类型及参数 
               A) 物理机使用 ext4 的最优化设置 
                     ➔  使用 raw 磁盘的最优性能设置 
                           ➢  cache类型 
                                 • none 
                                 • writeback 
                                 • writethrough 
                           ➢  驱动类型              
                                 • ide 
                                 • virtio 
                     ➔  使用 qcow2 磁盘的最优性能设置 
                           ➢  cache类型
                                 • none        
                                 • writeback 
                                 • writethrough 
                           ➢  驱动类型 
                                 • ide 
                                 • virtio 
                           ➢  是否preallocation  
                      ➔  比较得出使用 ext4 的虚拟机磁盘类型最优化设置 
 
              B) 物理机使用xfs磁盘的最优化设置 
                      ➔  使用 raw 磁盘的最优性能设置
                            ➢  cache类型 
                                 1. none
                                 2. writeback
                                 3. writethrough
                            ➢  驱动类型 
                                  1. ide
                                  2. virtio
                      ➔  使用 qcow2 磁盘的最优性能设置
                            ➢  cache类型 
                                  1. none
                                  2. writeback
                                  3. writethrough
                            ➢  驱动类型 
                                  1. ide
                                  2. virtio
                            ➢ 是否preallocation
                      ➔ 比较得出使用 ext4 的虚拟机磁盘类型最优化设置 
  
              C) 比较得出ext4和xfs那个更优秀 

物理机配置

服务器型号:DELL R410
CPU型号:CPU:Intel(R) Xeon(R) CPU E5620 2.4G*2
内存大小:8GB
硬盘大小:300*2
网卡:Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet * 2

虚拟机配置

在测试一个参数的时候为了防止其它因素的影响,不同的测试虚拟机配置会不同

CPU 的测试

虚拟机与物理机之间的性能对比
主要测试相对于物理机,虚拟机的性能损失有多少

虚拟机配置

1个VCPU 2G 内存 20G 硬盘用一个寻找质数的 C 程序,分别测试找出一百万,一千万,1 亿以内的质数所用的时间 








从上面的图可以看到,KVM 虚拟机相对于物理机的 CPU 性能损失非常小(不到 1%) 
 
由于物理机是 8 核的 CPU,我们猜想是不是他们运行在各自的 CPU,所以我们分别测试了同时在 2 个,4 个,6 个,8 个和 10 个虚拟机中运行测试程序所使用的时间,得到的结果是他们使用的时间相差不大,这里是同时在 10 个虚拟机中运行测试程序找出 1 亿中的质数所使用的时间对比图,我们在最后加上了在物理机中的运行时间 




我们猜想当同时运行的程序数(10)多于 CPU 数(8)时会有资源争抢或资源分配不均的情况出现,从上图可以看 到 KVM 于这些处理的很好,资源利用率很高,物理机和最慢的相差不到 20 秒(6%),资源分配也比较公正 

内存 

对于内存的测试多们使用了一个程序 memtester(注意不是 memtest),它能取给定大小的内存进行读写等一系 列的测试操作 




从这个图可以看出,相对于物理机,虚拟机的性能损失非常小 




上图是两个虚拟机同时运行测试所用的时间和物理机之间的对比,可以看出 KVM 对内存资源的分配很公平 

网络

我们在连接在相同交换机的另一台服务器上搭建 Web 服务器,让测试机和虚拟机同时下载 5G 的文件 




从这个图可以看到,公认的性能比较好的 virtio 驱动将虚拟机的网络性能发挥到极致,和物理机不相上下 




这个图再一次反映了 KVM 对资源分配的公平性 
 
我们还测试了同一台物理机上的虚拟机之间的传输速度可以稳定在 122MB/s 

硬盘 

磁盘的测试花了一些时间,因为有很多因素会影响磁盘性能,这个测试也没有覆盖所有可能的因素 先上数据 




对表的说明: 
      • 这个表记录了不同的参数对安装一个 CentOS 到虚拟机中所用的时间的影响
      • 安装使用相同的 kickstart
      • 使用 time 命令记录安装过程所使用的时间
      • 最后一列是将前一列的时间转化为秒数
      • 第一列的 xfs 和 ext4 指宿主机的存放虚拟磁盘镜像文件的分区类型,挂载参数都使用 default
      • Raw 和 Qcow2 指虚拟机的磁盘类型
      • ide 和 virtio 指虚拟机磁盘的驱动类型
      • pre 和 nopre 只是针对 qcow2 磁盘类型,创建磁盘文件时加上参数 preallocation=metadata 既为 pre
      • none,wt,wb,分别指缓存类型为 none, writethrough, writeback
      • 虚拟机都使用 1vcpu,2G 内存,40G 磁盘
 
下面从总体上看下他们的性能如何




从这个图不太容易看出哪个配置使用的时间最短,但非常容易看出最耗时的一个: 
 
宿主机使用 xfs,虚拟机使用 qcow2 磁盘,ide 驱动和 writethrough 缓存类型 
 
下面我们以由小到大的顺序,找出每个区域的最高性能,然后他们之间做对比 

首先看一下不同的缓存类型对性能的影响 









从两幅图可以得到的结论是:使用 writethrough 性能最差,none 和 writeback 相差不大 
 
这里插点缓存的知识KVM 缓存模式概览 通常,虚拟机使用宿主机上的一个文件保存它的数据,这个文件代表一个虚拟机作为正常的物理磁盘使用的虚 拟磁盘,然而,从宿主机的角度来看这个虚拟磁盘只是一个正常的数据文件并且可以对它缓存
在这种情况下,缓存是隐藏一些磁盘数据在内存中.当我们只在内存中存储上次读的数据,我们称之为读缓存,或 者 write-through 缓存.当我们还存储一些要写到硬盘的数据在内存中,在以后的某个时间再写到磁盘,我们称 之为读写缓存,或者 write-back 缓存,write-back 缓存通过将写磁盘请求缓存到高速内存中,有更高的性能,然 而它也比 write-through 更有可能丢失数据,因为后者只缓存写请求,写请求立即写到磁盘里 
 
因为磁盘 I/O 是非常重要的因素,Linux 和 Windows 系统通常使用 write-back 策略周期性的写到磁盘里,然 而,当然后虚拟化管理程序虚拟一个机器时,你可以有效的缓存一些数据两次(一次在宿主机的内在中,一次在虚 拟机的内存中),所以你可以取消宿主机对磁盘文件的缓存,让虚拟机自己管理它的缓存.些外,宿主机端的 write- back 策略很大程序上增加了数据丢失的可能性,然而,你很快会发现,新特性”barrier passing”的加入,你不用 再担心这个 

我们可以用一个图来更好的理解





假设传统的(没有 barrier-passing)程序:当虚拟机里的程序要写一些数据,通常数据保存到虚拟机的页缓存中. 页缓存会周期性的冲数据到虚拟磁盘设备也就是宿主机上的磁盘文件,另一方面,如果应用程序有一些非常重 要的数据要写,它可以绕过页缓存并且使用同步写方式,只有当写操作成功才返回,确保了所有的数据写到了虚 拟机的永久存储系统 
 
然而,在这一点上(写到虚拟机磁盘上)有三种可能:
         • 如果缓存策略是'writeback',数据会缓存到宿主机的页缓存中(红箭头) 
         • 如果缓存策略是'none',数据立即写到物理磁盘(灰箭头)
         • 如果缓存策略是'writethrough',数据将立即写到物理磁盘(蓝箭头) 
更多详情

下面我们看看 qcow2 磁盘使用和不使用 preallocation 的性能差异有多大 





从上图可以看出,不管宿主机使用 ext4 还是 xfs,虚拟机使用 ide 还是 virtio 驱动,使用 preallocation 都有性能 的提升,
这里有一个不问题:如果宿主机使用 xfs,创建 qcow2 磁盘镜像使用 preallocation 会很慢(40G 需要 8 分钟) 

下面我们来看看 ide 和 virtio 他们的性能对比 





很明显使用 virtio 是更明智的选择 

下面我们再看看 raw 和 qcow2 之间的对比

这里插一点 Raw 和 qcow2 的知识:raw 的优势(能找到的相关资料太少,不知道是不是理解有误):
• 简单,并能够导出为其他虚拟机的虚拟硬盘格式
• 根据实际使用量来占用空间使用量,而非原先设定的最大值(比如设定最高 20G,而实际只使用
3G)。——需要宿主分区支持 hole(比如 ext2 ext3 ntfs 等)
• 以后能够改变空间最大值(把最高值 20G 提高到 200G,qcow2 也可以,不过要转为 raw)
• 能够直接被宿主机挂载,不用开虚拟机即可在宿主和虚拟机间进行数据传输(注意,此时虚拟机不要开)
而qcow2 的优势:
• 更小的虚拟硬盘空间(尤其是宿主分区不支持 hole 的情况下)
• optional AES encryption, zlib based compression and support of multiple VM snapshots.原文在这里:http://www.linuxsir.org/bbs/thread368695.html 




从图表中可以看出,如果 qcow2 使用 preallocation, raw 的性能优势已经不是很明显 

下面看看 ext4 和 xfs 之间 的对比 





可以看到 ext4 性能要比 xfs 高,这可能是默认的挂载参数不能充分发挥 xfs 的性能 

最后,我们把时间最短的放到一起看到底那个最快 






总结 

CPU,内存都不是问题,对于硬盘,通过前面一系列的测试,我推荐使用以下配置:
• 使用 Ext4 做为宿主机磁盘格式
• 虚拟机用 qcow2+preallocation,
• 缓存使用 writeback
• 虚拟机网卡驱动使用 virtio文章来源于网络,如果有问题联系社区相关人员!
 
  查看全部
kvmlogo.gif

本测试试图找出以下问题的答案:
           1. 虚拟机相对于物理机性能损失有多严重(CPU/MEM/NET/DISK) 
           2. 对于多个虚拟机,KVM 对资源的分配是否公正
           3. 找出性能最好的物理机磁盘类型和虚拟机磁盘类型及参数 
               A) 物理机使用 ext4 的最优化设置 
                     ➔  使用 raw 磁盘的最优性能设置 
                           ➢  cache类型 
                                 • none 
                                 • writeback 
                                 • writethrough 
                           ➢  驱动类型              
                                 • ide 
                                 • virtio 
                     ➔  使用 qcow2 磁盘的最优性能设置 
                           ➢  cache类型
                                 • none        
                                 • writeback 
                                 • writethrough 
                           ➢  驱动类型 
                                 • ide 
                                 • virtio 
                           ➢  是否preallocation  
                      ➔  比较得出使用 ext4 的虚拟机磁盘类型最优化设置 
 
              B) 物理机使用xfs磁盘的最优化设置 
                      ➔  使用 raw 磁盘的最优性能设置
                            ➢  cache类型 
                                 1. none
                                 2. writeback
                                 3. writethrough
                            ➢  驱动类型 
                                  1. ide
                                  2. virtio
                      ➔  使用 qcow2 磁盘的最优性能设置
                            ➢  cache类型 
                                  1. none
                                  2. writeback
                                  3. writethrough
                            ➢  驱动类型 
                                  1. ide
                                  2. virtio
                            ➢ 是否preallocation
                      ➔ 比较得出使用 ext4 的虚拟机磁盘类型最优化设置 
  
              C) 比较得出ext4和xfs那个更优秀 


物理机配置


服务器型号:DELL R410
CPU型号:CPU:Intel(R) Xeon(R) CPU E5620 2.4G*2
内存大小:8GB
硬盘大小:300*2
网卡:Broadcom Corporation NetXtreme II BCM5709 Gigabit Ethernet * 2


虚拟机配置


在测试一个参数的时候为了防止其它因素的影响,不同的测试虚拟机配置会不同


CPU 的测试


虚拟机与物理机之间的性能对比 
主要测试相对于物理机,虚拟机的性能损失有多少


虚拟机配置


1个VCPU    2G 内存    20G 硬盘
用一个寻找质数的 C 程序,分别测试找出一百万,一千万,1 亿以内的质数所用的时间 
kc1.png

kc2.png

从上面的图可以看到,KVM 虚拟机相对于物理机的 CPU 性能损失非常小(不到 1%) 
 
由于物理机是 8 核的 CPU,我们猜想是不是他们运行在各自的 CPU,所以我们分别测试了同时在 2 个,4 个,6 个,8 个和 10 个虚拟机中运行测试程序所使用的时间,得到的结果是他们使用的时间相差不大,这里是同时在 10 个虚拟机中运行测试程序找出 1 亿中的质数所使用的时间对比图,我们在最后加上了在物理机中的运行时间 
kc3.png

我们猜想当同时运行的程序数(10)多于 CPU 数(8)时会有资源争抢或资源分配不均的情况出现,从上图可以看 到 KVM 于这些处理的很好,资源利用率很高,物理机和最慢的相差不到 20 秒(6%),资源分配也比较公正 


内存 


对于内存的测试多们使用了一个程序 memtester(注意不是 memtest),它能取给定大小的内存进行读写等一系 列的测试操作 
kc4.png

从这个图可以看出,相对于物理机,虚拟机的性能损失非常小 
kc5.png

上图是两个虚拟机同时运行测试所用的时间和物理机之间的对比,可以看出 KVM 对内存资源的分配很公平 


网络


我们在连接在相同交换机的另一台服务器上搭建 Web 服务器,让测试机和虚拟机同时下载 5G 的文件 
kc6.png

从这个图可以看到,公认的性能比较好的 virtio 驱动将虚拟机的网络性能发挥到极致,和物理机不相上下 
kc7.png

这个图再一次反映了 KVM 对资源分配的公平性 
 
我们还测试了同一台物理机上的虚拟机之间的传输速度可以稳定在 122MB/s 


硬盘 


磁盘的测试花了一些时间,因为有很多因素会影响磁盘性能,这个测试也没有覆盖所有可能的因素 先上数据 
kc8.png

对表的说明: 
      • 这个表记录了不同的参数对安装一个 CentOS 到虚拟机中所用的时间的影响
      • 安装使用相同的 kickstart
      • 使用 time 命令记录安装过程所使用的时间
      • 最后一列是将前一列的时间转化为秒数
      • 第一列的 xfs 和 ext4 指宿主机的存放虚拟磁盘镜像文件的分区类型,挂载参数都使用 default
      • Raw 和 Qcow2 指虚拟机的磁盘类型
      • ide 和 virtio 指虚拟机磁盘的驱动类型
      • pre 和 nopre 只是针对 qcow2 磁盘类型,创建磁盘文件时加上参数 preallocation=metadata 既为 pre
      • none,wt,wb,分别指缓存类型为 none, writethrough, writeback
      • 虚拟机都使用 1vcpu,2G 内存,40G 磁盘
 
下面从总体上看下他们的性能如何
kc9.png

从这个图不太容易看出哪个配置使用的时间最短,但非常容易看出最耗时的一个: 
 
宿主机使用 xfs,虚拟机使用 qcow2 磁盘,ide 驱动和 writethrough 缓存类型 
 
下面我们以由小到大的顺序,找出每个区域的最高性能,然后他们之间做对比 


首先看一下不同的缓存类型对性能的影响 


kc10.png

kc11.png

从两幅图可以得到的结论是:使用 writethrough 性能最差,none 和 writeback 相差不大 
 
这里插点缓存的知识
KVM 缓存模式概览 通常,虚拟机使用宿主机上的一个文件保存它的数据,这个文件代表一个虚拟机作为正常的物理磁盘使用的虚 拟磁盘,然而,从宿主机的角度来看这个虚拟磁盘只是一个正常的数据文件并且可以对它缓存

在这种情况下,缓存是隐藏一些磁盘数据在内存中.当我们只在内存中存储上次读的数据,我们称之为读缓存,或 者 write-through 缓存.当我们还存储一些要写到硬盘的数据在内存中,在以后的某个时间再写到磁盘,我们称 之为读写缓存,或者 write-back 缓存,write-back 缓存通过将写磁盘请求缓存到高速内存中,有更高的性能,然 而它也比 write-through 更有可能丢失数据,因为后者只缓存写请求,写请求立即写到磁盘里 
 
因为磁盘 I/O 是非常重要的因素,Linux 和 Windows 系统通常使用 write-back 策略周期性的写到磁盘里,然 而,当然后虚拟化管理程序虚拟一个机器时,你可以有效的缓存一些数据两次(一次在宿主机的内在中,一次在虚 拟机的内存中),所以你可以取消宿主机对磁盘文件的缓存,让虚拟机自己管理它的缓存.些外,宿主机端的 write- back 策略很大程序上增加了数据丢失的可能性,然而,你很快会发现,新特性”barrier passing”的加入,你不用 再担心这个 


我们可以用一个图来更好的理解


kc12.png

假设传统的(没有 barrier-passing)程序:当虚拟机里的程序要写一些数据,通常数据保存到虚拟机的页缓存中. 页缓存会周期性的冲数据到虚拟磁盘设备也就是宿主机上的磁盘文件,另一方面,如果应用程序有一些非常重 要的数据要写,它可以绕过页缓存并且使用同步写方式,只有当写操作成功才返回,确保了所有的数据写到了虚 拟机的永久存储系统 
 
然而,在这一点上(写到虚拟机磁盘上)有三种可能:
         • 如果缓存策略是'writeback',数据会缓存到宿主机的页缓存中(红箭头) 
         • 如果缓存策略是'none',数据立即写到物理磁盘(灰箭头)
         • 如果缓存策略是'writethrough',数据将立即写到物理磁盘(蓝箭头) 
更多详情


下面我们看看 qcow2 磁盘使用和不使用 preallocation 的性能差异有多大 


kc13.png

从上图可以看出,不管宿主机使用 ext4 还是 xfs,虚拟机使用 ide 还是 virtio 驱动,使用 preallocation 都有性能 的提升,
这里有一个不问题:如果宿主机使用 xfs,创建 qcow2 磁盘镜像使用 preallocation 会很慢(40G 需要 8 分钟) 


下面我们来看看 ide 和 virtio 他们的性能对比 


kc14.png

很明显使用 virtio 是更明智的选择 


下面我们再看看 raw 和 qcow2 之间的对比


这里插一点 Raw 和 qcow2 的知识:
raw 的优势(能找到的相关资料太少,不知道是不是理解有误):
• 简单,并能够导出为其他虚拟机的虚拟硬盘格式
• 根据实际使用量来占用空间使用量,而非原先设定的最大值(比如设定最高 20G,而实际只使用
3G)。——需要宿主分区支持 hole(比如 ext2 ext3 ntfs 等)
• 以后能够改变空间最大值(把最高值 20G 提高到 200G,qcow2 也可以,不过要转为 raw)
• 能够直接被宿主机挂载,不用开虚拟机即可在宿主和虚拟机间进行数据传输(注意,此时虚拟机不要开)
而qcow2 的优势:
• 更小的虚拟硬盘空间(尤其是宿主分区不支持 hole 的情况下)
• optional AES encryption, zlib based compression and support of multiple VM snapshots.
原文在这里:http://www.linuxsir.org/bbs/thread368695.html 
kc15.png

从图表中可以看出,如果 qcow2 使用 preallocation, raw 的性能优势已经不是很明显 


下面看看 ext4 和 xfs 之间 的对比 


kc16.png

可以看到 ext4 性能要比 xfs 高,这可能是默认的挂载参数不能充分发挥 xfs 的性能 


最后,我们把时间最短的放到一起看到底那个最快 


kc17.png


总结 


CPU,内存都不是问题,对于硬盘,通过前面一系列的测试,我推荐使用以下配置:
• 使用 Ext4 做为宿主机磁盘格式
• 虚拟机用 qcow2+preallocation,
• 缓存使用 writeback
• 虚拟机网卡驱动使用 virtio
文章来源于网络,如果有问题联系社区相关人员!
 
 

浅谈docker文件系统分层与隔离

采菊篱下 发表了文章 • 0 个评论 • 1450 次浏览 • 2015-08-28 01:27 • 来自相关话题

   
    Docker 的很多特性都表现在它所使用的文件系统上,比如大家都知道docker的文件系统是分层的,所以它可以快速迭代,可以回滚。下面就聊一下我对docker文件系统的理解
 
    Docker 使用的支持的文件系统有以下几种: aufs、devicemapper、btrfs  Vfs 我们先来介绍一下aufs

一、  Aufs(advanced multi layered unification filesystem)

    Aufs直译过来就是高级分层统一文件系统。做为一种Union FS 它支持将不同的目录挂载到同一个虚拟文件系统下. 这个怎么理解呢。通过一条命令我们来看一下吧。mount -t aufs -o br=/tmp/dir1=ro:/tmp/dir2=rw none /tmp/newfs
[]-o 指定mount传递给文件系统的参数[/][]br 指定需要挂载的文件夹,这里包括dir1和dir2[/][]ro/rw 指定文件的权限只读和可读写[/][]none 这里没有设备,用none表示[/]
    这个结果是什么样子的呢。 就是把/tmp/dir1 t和/tmp/dir2  合并之后挂载到/tmp/newfs ,如果这时在/tmp/dir1 下创建一个文件a  /tmp/dir2下创建一个文件b 则  在/tmp/newfs 会看到a,b 这两个文件,并且a 是只读的, 如果有相同的文件则以先挂载的为准,后面挂载的操作会被忽略掉
 
   通过对Aufs的理解,大家可以想像一下docker所谓的“layer”的概念。还是实际的例子说明一下。

    一个镜像通过docker save  保存之后 会被打成一个tar 包,我们来看下这个tar包里都有些什么?docker save cloud_jiankongbao:01.tar cloud_jiankongbao:01    通过上面的语句我们把镜像保存出下来。可以看到,保存下来的是tar 包。 不是.iso文件^_^,镜像解压之后是什么呢?ls .
a005304e4e74c1541988d3d1abb170e338c1d45daee7151f8e82f8460634d329
d9bde94c518a16a886514758b6b4431200145ecd58e30c5633ac3c0256544d77
f1b10cd842498c23d206ee0cbeaa9de8d2ae09ff3c7af2723a9e337a6965d639
fb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f
repositories    出现了四个目录文件,再通过docker images --tree
└─f1b10cd84249 Virtual Size: 0 B
└─fb9cc58bde0c Virtual Size: 203.1 MB
└─a005304e4e74 Virtual Size: 203.1 MB
└─d9bde94c518a Virtual Size: 1.957 GB Tags: cloud_jiankongbao:01    大家可以看到,4个目录其实分别是4个ID(注每次使用docker commit 提供对docker的修改之后就会产生一个新的id,就是通过这个ID可以实现对镜像的回滚)。每个目录下有json  layer.tar  VERSION 这三个文件。我们再看一下layer.tar cd fb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f;tar -xf layer.tar;ls

ls fb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f/
bin etc json lib lost+found mnt proc sbin srv tmp var
dev home layer.tar lib64 media opt root selinux sys usr VERSION    这里存放的系统文件。

    我们再看一下镜像的4个不同ID的系统。

    f1b10cd84249 这个镜像是初始镜像,大小为0, fb9cc58bde0c 这个镜像是在f1b10cd84249基础上创建新的镜像,a005304e4e74是以fb9cc58bde0c为基础创建新的镜像。是树状继承的关系。我们再看下bin目录下的文件ls a005304e4e74c1541988d3d1abb170e338c1d45daee7151f8e82f8460634d329/bin/
gtar tarls fb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f/bin/
arch cpio egrep gunzip logger mountpoint raw sleep true
awk cut env gzip login mv readlink sort umount
basename date ex hostname ls netstat rm stty uname
bash dd false ipcalc lsblk nice rmdir su unlink
cat df fgrep iptables-xml mkdir nisdomainname rpm sync usleep
chgrp dmesg find iptables-xml-1.4.7 mknod ping rvi taskset vi
chmod dnsdomainname findmnt kill mktemp ping6 rview touch view
chown domainname gawk link more ps sed tracepath ypdomainname
cp echo grep ln mount pwd sh tracepath6 zcat
    a005304e4e74 只有两个文件 fb9cc58bde0c包括了大部分bin下的文件,这就是Aufs,理解起来感觉有点像增量备份。

二、简单的说一下devicemapper 

    devicemapper是利用了Snapshot 和Thinly-Provisioned Snapshot两种原理。将多个快照挂在同一个卷下从而实现文件系统的分层。不过使用devicemapper 的话一个container的大小最大只能是10G。
 
    在启动docker daemon时用参数-s 指定:  docker -d -s devicemapper
 
    关于隔离是怎么实现的呢,当容器基于镜像启动之后,每个容器都会获得自己的写读可写的文件系统层。原镜像的那部分文件系统是只读的,从而实现每个容器的在文件系统上的离隔。
 
   平时大家都在说dokcer 是弱隔离的,为什么呢?因为他没有隔离的很彻底,比如内核,内核是跟大家共用的,跟宿主机共用同一个内核,SELinux、 Cgroups以及/sys、/proc/sys、/dev/sd*等目录下的资源是与宿主机共用的。

   如果要隔离的彻底那就是VM了,而且如果dockers要想实现这些隔离就必然要牺牲一下现在轻量级的特性。那还不如直接用虚拟机好了!
文章转载出处 查看全部
df1.png
   
    Docker 的很多特性都表现在它所使用的文件系统上,比如大家都知道docker的文件系统是分层的,所以它可以快速迭代,可以回滚。下面就聊一下我对docker文件系统的理解
 
    Docker 使用的支持的文件系统有以下几种: aufs、devicemapper、btrfs  Vfs 我们先来介绍一下aufs


一、  Aufs(advanced multi layered unification filesystem)


    Aufs直译过来就是高级分层统一文件系统。做为一种Union FS 它支持将不同的目录挂载到同一个虚拟文件系统下. 这个怎么理解呢。通过一条命令我们来看一下吧。
mount -t aufs -o br=/tmp/dir1=ro:/tmp/dir2=rw none /tmp/newfs

    []-o 指定mount传递给文件系统的参数[/][]br 指定需要挂载的文件夹,这里包括dir1和dir2[/][]ro/rw 指定文件的权限只读和可读写[/][]none 这里没有设备,用none表示[/]

    这个结果是什么样子的呢。 就是把/tmp/dir1 t和/tmp/dir2  合并之后挂载到/tmp/newfs ,如果这时在/tmp/dir1 下创建一个文件a  /tmp/dir2下创建一个文件b 则  在/tmp/newfs 会看到a,b 这两个文件,并且a 是只读的, 如果有相同的文件则以先挂载的为准,后面挂载的操作会被忽略掉
 
   通过对Aufs的理解,大家可以想像一下docker所谓的“layer”的概念。还是实际的例子说明一下。

    一个镜像通过docker save  保存之后 会被打成一个tar 包,我们来看下这个tar包里都有些什么?
docker save cloud_jiankongbao:01.tar cloud_jiankongbao:01
    通过上面的语句我们把镜像保存出下来。可以看到,保存下来的是tar 包。 不是.iso文件^_^,镜像解压之后是什么呢?
ls . 
a005304e4e74c1541988d3d1abb170e338c1d45daee7151f8e82f8460634d329
d9bde94c518a16a886514758b6b4431200145ecd58e30c5633ac3c0256544d77
f1b10cd842498c23d206ee0cbeaa9de8d2ae09ff3c7af2723a9e337a6965d639
fb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f
repositories
    出现了四个目录文件,再通过
docker images --tree
└─f1b10cd84249 Virtual Size: 0 B
└─fb9cc58bde0c Virtual Size: 203.1 MB
└─a005304e4e74 Virtual Size: 203.1 MB
└─d9bde94c518a Virtual Size: 1.957 GB Tags: cloud_jiankongbao:01
    大家可以看到,4个目录其实分别是4个ID(注每次使用docker commit 提供对docker的修改之后就会产生一个新的id,就是通过这个ID可以实现对镜像的回滚)。每个目录下有json  layer.tar  VERSION 这三个文件。我们再看一下layer.tar 
cd fb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f;tar -xf layer.tar;ls

ls fb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f/
bin etc json lib lost+found mnt proc sbin srv tmp var
dev home layer.tar lib64 media opt root selinux sys usr VERSION
    这里存放的系统文件。

    我们再看一下镜像的4个不同ID的系统。

    f1b10cd84249 这个镜像是初始镜像,大小为0, fb9cc58bde0c 这个镜像是在f1b10cd84249基础上创建新的镜像,a005304e4e74是以fb9cc58bde0c为基础创建新的镜像。是树状继承的关系。我们再看下bin目录下的文件
ls a005304e4e74c1541988d3d1abb170e338c1d45daee7151f8e82f8460634d329/bin/
gtar tar
ls fb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f/bin/
arch cpio egrep gunzip logger mountpoint raw sleep true
awk cut env gzip login mv readlink sort umount
basename date ex hostname ls netstat rm stty uname
bash dd false ipcalc lsblk nice rmdir su unlink
cat df fgrep iptables-xml mkdir nisdomainname rpm sync usleep
chgrp dmesg find iptables-xml-1.4.7 mknod ping rvi taskset vi
chmod dnsdomainname findmnt kill mktemp ping6 rview touch view
chown domainname gawk link more ps sed tracepath ypdomainname
cp echo grep ln mount pwd sh tracepath6 zcat
    a005304e4e74 只有两个文件 fb9cc58bde0c包括了大部分bin下的文件,这就是Aufs,理解起来感觉有点像增量备份。


二、简单的说一下devicemapper 


    devicemapper是利用了Snapshot 和Thinly-Provisioned Snapshot两种原理。将多个快照挂在同一个卷下从而实现文件系统的分层。不过使用devicemapper 的话一个container的大小最大只能是10G。
 
    在启动docker daemon时用参数-s 指定:  docker -d -s devicemapper
 
    关于隔离是怎么实现的呢,当容器基于镜像启动之后,每个容器都会获得自己的写读可写的文件系统层。原镜像的那部分文件系统是只读的,从而实现每个容器的在文件系统上的离隔。
 
   平时大家都在说dokcer 是弱隔离的,为什么呢?因为他没有隔离的很彻底,比如内核,内核是跟大家共用的,跟宿主机共用同一个内核,SELinux、 Cgroups以及/sys、/proc/sys、/dev/sd*等目录下的资源是与宿主机共用的。

   如果要隔离的彻底那就是VM了,而且如果dockers要想实现这些隔离就必然要牺牲一下现在轻量级的特性。那还不如直接用虚拟机好了!
文章转载出处

我的docker为什么总是拉去镜像失败呢

采菊篱下 回复了问题 • 2 人关注 • 3 个回复 • 1293 次浏览 • 2015-08-27 00:01 • 来自相关话题

Docker主机间怎么共享数据卷

OpenSkill 发表了文章 • 0 个评论 • 2120 次浏览 • 2015-08-26 00:07 • 来自相关话题

     Docker容器在不同的主机间共享数据是一件很棘手的事情。本文从"Docker容器实践"中采取,我们将研究一个轻量级,一个更复杂的方式在不同的主机间共享Docker数据卷。
     尽管容器之间共享同一台主机上的数据变得更为简便,跨主机间共享Docker数据卷比较棘手。数据容器是解决这个问题的一个方法,但如果数据经常变化或特别大,这样做会变得笨拙。
     我们要考察两个解决这个问题的方法。第一个是一个轻量级的分布式解决方案使用BitTorrent协议,仅仅需要安装Docker。 第二是使用NFS,并引入基础设施的容器的概念的更复杂的解决方案。

方法一:分布式数据卷BitTorrent的同步

     当Docker在一个组中实验,希望在组内共享大量数据,但是可能共享服务器没有足够的能力分配资源。懒惰的解决方案是在你需要他们的时候复制其他团队成员的最新文件,这将对一个更大的组失去控制。
     对此的解决方案是使用一个分散的工具共享文件–没有专门的资源要求。
问题:
     你想在互联网上共享跨主机的卷
解决方法:
     使用BitTorrent同步image共享卷
讨论:
    下面说明图显示了我们的目标,结束与设置:



    A - 该BTSync服务器是一个拥有我们将要共享的/data数据卷Docker容器
B - 在同一主机上设置一个容器从BTSync服务器上挂载数据卷
C - 在一个单独的网络中的其他主机,在BTSync服务器生成一个密钥,客户端可以通过引用BitTorrent协议来访问共享数据。
D - 在另外一台主机上的BTSync客户端,从第一主机BTSync服务器挂载数据同步更新/data数据。
E - 容器从BTSync客户端挂载数据卷     最终的结果是卷/data-即方便地同步在互联网上,而不需要任何复杂的设置。
     在您的主服务器上运行这些命令来设置第一台主机上的容器:[host1]$ [#A]docker run -d -p 8888:8888 -p 55555:55555 --name btsync ctlc/btsync
$ [#B]docker logs btsync
Starting btsync with secret: [#C]ALSVEUABQQ5ILRS2OQJKAOKCU5SIIP6A3 By using this application, you agree to our Privacy Policy and Terms. http://www.bittorrent.com/legal/privacy http://www.bittorrent.com/legal/terms-of-use
total physical memory 536870912 max disk cache 2097152 Using IP address 172.17.4.121
[host1]$ [#D]docker run -i -t --volumes-from btsync ubuntu /bin/bash
$ touch /data/shared_from_server_one [#E] $ ls /data shared_from_server_one     A -运行发表CTLC / btsync image btsync守护程序容器调用并打开所需的端口
     B -获取 btsync容器的输出,所以我们可以记下key
     C -记下key-不同的运行产生有所不同
     D-启动一个交互式的容器从btsync服务器的卷
     E-添加文件到/data
     在第二个服务器上打开一个终端,运行以下命令来设置数据同步[host2]$ docker run -d
--name btsync-client -p 8888:8888 -p
55555:55555 ctlc/btsync ALSVEUABQQ5ILRS2OQJKAOKCU5SIIP6A3 [#A]
[host2]$ docker run -i -t --volumes-from btsync-client ubuntu bash [#B] $ ls /data shared_from_server_one [#C] $ touch /data/shared_from_server_two [#D] $ ls /data
shared_from_server_one shared_from_server_two     A -启动 btsync客户端容器与host1上的守护程序运行生成的密钥守护进程
     B -启动安装卷从我们的客户守护进程的互动容器
     C - host1上创建的文件已被转移到主机2
     D -创建 host2上的第二个文件
     回到主机1的运行容器,我们应该看到的文件,就像第一次是在主机之间进行同步:$ ls /data
shared_from_server_one shared_from_server_two      注:文件同步是没有时间保证,所以你可能要等待同步数据。这是特别真实的更大的文件。

      警告:由于数据被发送到互联网和处理的协议,你没有控制,不要依赖于此,如果你有任何有意义的安全性,可扩展性或性能约束。

方法二:通过NFS共享数据

      在一些大公司极有可能已经在使用NFS,NFS是一种行之有效的选项作为文件中心服务。Docker想要工作,它能够访问这些共享文件通常是很重要的!
      然而,Docker不支持NFS开箱即用和每个集装箱上安装NFS客户端,以便能够挂载远程文件夹不被认为是最佳时实践。相反,建议的方法是有一个容器用作从NFS翻译为Docker更友好的概念–卷!
问题:
      你要无缝访问远程文件系统通过NFS
解决方法:
      使用基础设施的数据容器代理访问
讨论
      这种技术建立在数据容器技术之上。
下图给出了这个抽象的概念:




      NFS服务器暴露内部目录的文件夹/出口,这是安装在主机绑定。Docker主机再将这个文件夹使用NFS协议mount到/mnt文件夹。然后,一个所谓的基础设施容器被创建,它结合了安装文件夹。
     这似乎有点过度设计乍一看,但好处是,它提供了一个间接层就Docker容器而言:他们需要做的是安装卷从预先约定的基础设施的容器,谁是负责基础设施可以担心的内部管道,可用性,网络等。
     彻底处理NFS是超出了本书的范围。然而,我们去通过一台主机上建立这样一个共享的步骤(即NFS服务器的元素在同一主机作为Docker容器)。这已经在Ubuntu 14.04测试。
     想象一下,你想分享你的主机/opt/test/db,其中包含的文件mybigdb.db。
     使用root,安装NFS服务器创建/export目录,并开放权限:apt-get install nfs-kernel-server mkdir /export chmod 777 /export     现在挂载db目录/opt/test/db到/export$ mount --bind /opt/test/db /export     现在你应该可以看到 /opt/test/db中的挂载的内容
     现在加入这一行到您的etc/exports文件中/export [#A]127.0.0.1([#B]ro,fsid=0,insecure,no_subtree_check,async)      A -对于这个概念证明的例子中我们对127.0.0.1,这违背了对象有点安装在本地。 在真实的场景中,你会锁定下来的一类IP地址,如192.168.1.0/24的。 如果你真的很喜欢玩火,你可以打开它的世界,而不是127.0.0.1!
     B -为安全起见,我们安装件只读这里,*但是你可以用RW更换RO安装读写。 请记住,如果你这样做,那么你就需要异步标志出现后添加no_root_squash会标志 - 但考虑安全性在此之前沙坑外面去!
挂载NFS上的目录/ mnt目录,出口,我们在指定的文件系统的/ etc / exports的上面,然后重新启动NFS服务,拿起变化: $ mount -t nfs 127.0.0.1:/export /mnt
$ exportfs -a
$ service nfs-kernel-server restart     现在您已经准备好运行基础设施的容器:$ docker run -ti --name nfs_client --privileged -v /mnt:/mnt busybox /bin/true      TODO:检查一个以上要求
      现在,我们可以运行 - 没有特权,或底层实现知识 - 目录,我们希望访问:$ docker run -ti --volumes-from nfs_client debian /bin/bash root@079d70f79d84:/# ls /mnt myb root@079d70f79d84:/# cd /mnt root@079d70f79d84:/mnt# touch asd touch: cannot touch `asd': Read-only file system     提示:如果你有很多这些容器来管理使用的运营效率的命名约定,你可以通过命名约定管理操作更容易,例如——名为nfs_client_opt_database_live容器暴露/opt/database/live路径。
这种模式的一个共享资源,在多个容器中使用的其他人使用的共享资源,是一个强大的,可以使开发工作流程更简单。
原文地址 查看全部
dk1.png

     Docker容器在不同的主机间共享数据是一件很棘手的事情。本文从"Docker容器实践"中采取,我们将研究一个轻量级,一个更复杂的方式在不同的主机间共享Docker数据卷。
     尽管容器之间共享同一台主机上的数据变得更为简便,跨主机间共享Docker数据卷比较棘手。数据容器是解决这个问题的一个方法,但如果数据经常变化或特别大,这样做会变得笨拙。
     我们要考察两个解决这个问题的方法。第一个是一个轻量级的分布式解决方案使用BitTorrent协议,仅仅需要安装Docker。 第二是使用NFS,并引入基础设施的容器的概念的更复杂的解决方案。


方法一:分布式数据卷BitTorrent的同步


     当Docker在一个组中实验,希望在组内共享大量数据,但是可能共享服务器没有足够的能力分配资源。懒惰的解决方案是在你需要他们的时候复制其他团队成员的最新文件,这将对一个更大的组失去控制。
     对此的解决方案是使用一个分散的工具共享文件–没有专门的资源要求。
问题:
     你想在互联网上共享跨主机的卷
解决方法:
     使用BitTorrent同步image共享卷
讨论:
    下面说明图显示了我们的目标,结束与设置:
dk2.png
   
     A - 该BTSync服务器是一个拥有我们将要共享的/data数据卷Docker容器
B - 在同一主机上设置一个容器从BTSync服务器上挂载数据卷
C - 在一个单独的网络中的其他主机,在BTSync服务器生成一个密钥,客户端可以通过引用BitTorrent协议来访问共享数据。
D - 在另外一台主机上的BTSync客户端,从第一主机BTSync服务器挂载数据同步更新/data数据。
E - 容器从BTSync客户端挂载数据卷
     最终的结果是卷/data-即方便地同步在互联网上,而不需要任何复杂的设置。
     在您的主服务器上运行这些命令来设置第一台主机上的容器:
[host1]$ [#A]docker run -d -p 8888:8888 -p 55555:55555 --name btsync ctlc/btsync
$ [#B]docker logs btsync
Starting btsync with secret: [#C]ALSVEUABQQ5ILRS2OQJKAOKCU5SIIP6A3 By using this application, you agree to our Privacy Policy and Terms. http://www.bittorrent.com/legal/privacy http://www.bittorrent.com/legal/terms-of-use
total physical memory 536870912 max disk cache 2097152 Using IP address 172.17.4.121
[host1]$ [#D]docker run -i -t --volumes-from btsync ubuntu /bin/bash
$ touch /data/shared_from_server_one [#E] $ ls /data shared_from_server_one
     A -运行发表CTLC / btsync image btsync守护程序容器调用并打开所需的端口
     B -获取 btsync容器的输出,所以我们可以记下key
     C -记下key-不同的运行产生有所不同
     D-启动一个交互式的容器从btsync服务器的卷
     E-添加文件到/data
     在第二个服务器上打开一个终端,运行以下命令来设置数据同步
[host2]$ docker run -d
--name btsync-client -p 8888:8888 -p
55555:55555 ctlc/btsync ALSVEUABQQ5ILRS2OQJKAOKCU5SIIP6A3 [#A]
[host2]$ docker run -i -t --volumes-from btsync-client ubuntu bash [#B] $ ls /data shared_from_server_one [#C] $ touch /data/shared_from_server_two [#D] $ ls /data
shared_from_server_one shared_from_server_two
     A -启动 btsync客户端容器与host1上的守护程序运行生成的密钥守护进程
     B -启动安装卷从我们的客户守护进程的互动容器
     C - host1上创建的文件已被转移到主机2
     D -创建 host2上的第二个文件
     回到主机1的运行容器,我们应该看到的文件,就像第一次是在主机之间进行同步:
$ ls /data
shared_from_server_one shared_from_server_two
      注:文件同步是没有时间保证,所以你可能要等待同步数据。这是特别真实的更大的文件。

      警告:由于数据被发送到互联网和处理的协议,你没有控制,不要依赖于此,如果你有任何有意义的安全性,可扩展性或性能约束。


方法二:通过NFS共享数据


      在一些大公司极有可能已经在使用NFS,NFS是一种行之有效的选项作为文件中心服务。Docker想要工作,它能够访问这些共享文件通常是很重要的!
      然而,Docker不支持NFS开箱即用和每个集装箱上安装NFS客户端,以便能够挂载远程文件夹不被认为是最佳时实践。相反,建议的方法是有一个容器用作从NFS翻译为Docker更友好的概念–卷!
问题:
      你要无缝访问远程文件系统通过NFS
解决方法:
      使用基础设施的数据容器代理访问
讨论
      这种技术建立在数据容器技术之上。
下图给出了这个抽象的概念:
dk3.png

      NFS服务器暴露内部目录的文件夹/出口,这是安装在主机绑定。Docker主机再将这个文件夹使用NFS协议mount到/mnt文件夹。然后,一个所谓的基础设施容器被创建,它结合了安装文件夹。
     这似乎有点过度设计乍一看,但好处是,它提供了一个间接层就Docker容器而言:他们需要做的是安装卷从预先约定的基础设施的容器,谁是负责基础设施可以担心的内部管道,可用性,网络等。
     彻底处理NFS是超出了本书的范围。然而,我们去通过一台主机上建立这样一个共享的步骤(即NFS服务器的元素在同一主机作为Docker容器)。这已经在Ubuntu 14.04测试。
     想象一下,你想分享你的主机/opt/test/db,其中包含的文件mybigdb.db。
     使用root,安装NFS服务器创建/export目录,并开放权限:
apt-get install nfs-kernel-server mkdir /export chmod 777 /export
     现在挂载db目录/opt/test/db到/export
$ mount --bind /opt/test/db /export
     现在你应该可以看到 /opt/test/db中的挂载的内容
     现在加入这一行到您的etc/exports文件中
/export       [#A]127.0.0.1([#B]ro,fsid=0,insecure,no_subtree_check,async)
      A -对于这个概念证明的例子中我们对127.0.0.1,这违背了对象有点安装在本地。 在真实的场景中,你会锁定下来的一类IP地址,如192.168.1.0/24的。 如果你真的很喜欢玩火,你可以打开它的世界,而不是127.0.0.1!
     B -为安全起见,我们安装件只读这里,*但是你可以用RW更换RO安装读写。 请记住,如果你这样做,那么你就需要异步标志出现后添加no_root_squash会标志 - 但考虑安全性在此之前沙坑外面去!
挂载NFS上的目录/ mnt目录,出口,我们在指定的文件系统的/ etc / exports的上面,然后重新启动NFS服务,拿起变化: 
$ mount -t nfs 127.0.0.1:/export /mnt
$ exportfs -a
$ service nfs-kernel-server restart
     现在您已经准备好运行基础设施的容器:
$ docker run -ti --name nfs_client --privileged -v /mnt:/mnt busybox /bin/true
      TODO:检查一个以上要求
      现在,我们可以运行 - 没有特权,或底层实现知识 - 目录,我们希望访问:
$ docker run -ti --volumes-from nfs_client debian /bin/bash root@079d70f79d84:/# ls /mnt myb root@079d70f79d84:/# cd /mnt root@079d70f79d84:/mnt# touch asd touch: cannot touch `asd': Read-only file system
     提示:如果你有很多这些容器来管理使用的运营效率的命名约定,你可以通过命名约定管理操作更容易,例如——名为nfs_client_opt_database_live容器暴露/opt/database/live路径。
这种模式的一个共享资源,在多个容器中使用的其他人使用的共享资源,是一个强大的,可以使开发工作流程更简单。
原文地址