发布于 2015-12-05 11:06:13 | 759 次阅读 | 评论: 0 | 来源: 网络整理
Linux上的Mesos可支持 单容器网络监控和隔离,每个活动容器的网络统计信息会被写入slave节点的 /monitor/statistics.json
。
网络隔离 功能可避免 单个容器 占用过多可用端口,消耗过多带宽以及过分阻滞其他容器的信息传输等。 网络隔离功能对于大部分运行在slave节点的任务(端口绑定为0,且由内核分配端口)来说使透明的。
容器网络监控和隔离在默认配置下是不开启的。需要在编译时,设置相关配置,并安装相关依赖,才可开启。
单容器网络监控和分隔 只能在 kernel版本大于3.6 的linux 里使用,另外,linux kernel必须包含以下补丁(kernel 3.15后,这些补丁已经包含进内核中)。
slave节点需要的依赖:
若是从源码编译,则需要libnl3开发版:
开启 单容器网络监控和隔离,需要在 编译配置中设定:
$ ./configure --with-network-isolator
$ make
节点网络监控和隔离需要在slave节点,加入下面参数 设置:
--isolation="network/port_mapping"
若编译的时候没有开启 节点网络监控和隔离 支持,则会无法启动,并输出错误信息如下:
I0708 00:17:08.080271 44267 containerizer.cpp:111] Using isolation: network/port_mapping
Failed to create a containerizer: Could not create MesosContainerizer: Unknown or unsupported
isolator: network/port_mapping
在没有 网络隔离功能的时候,所有容器都将共用slave节点的IP地址,绑定操作系统允许的任意端口。
而当网络隔离启用的时候,slave节点上的每个容器将有单独的网络链路(基于Linux network namespaces),虽然仍然共用被控的对公IP(这样的好处是不用更改 服务发现机制)。slave节点会根据设定的可用端口范围给容器分配端口,只有端口内的网络链路才可用。
应用若向核心申请分配端口,则会在 容器所设的可用端口中选一个。应用虽然也可以在这个可用端口范围外绑定一个端口,但这样的结果是主机将无视其网络请求,网络链路不通。
Mesos给容器提供两个可用端口范围:
Mesos从系统分配到的临时端口ephemeral:用于容器。
另外,主机本身也会需要临时端口用于网络通讯,也就是总共有三个不重叠的端口范围需要在主机设置。
用命令sysctl net.ipv4.ip_local_port_range
可查看目前主机的临时端口范围。若需要更改,可在/etc/sysctl.conf
里设置,注意不要设置其他进程使用的端口,设置完后重启,使其生效。
例子如下:把主机临时端口设置为57345到61000了。
# net.ipv4.ip_local_port_range defines the host ephemeral port range, by
# default 32768-61000. We reduce this range to allow the Mesos slave to
# allocate ports 32768-57344
# net.ipv4.ip_local_port_range = 32768 61000
net.ipv4.ip_local_port_range = 57345 61000
容器的临时和非临时端口,使用--resources
来设置。非临时端口是由master节点提供的,将会被分配给应用。
临时端口则会被 slave节点分配,使用 ephemeral_ports_per_container
(默认 1024) 分配给容器。每个被控上的容器因为网络资源有限,其数量也是有限的:容器最大可用数量=可用临时端口量/每容器端口数。
number of ephemeral_ports / ephemeral_ports_per_container
master节点的 --max_executors_per_slave
(每slave节点最大执行器数)设定用于避免给slave节点分配过多的执行器而致临时端口超额。
建议把ephemeral_ports_per_container
设为2的幂数,比如512,1024,临时端口则是ephemeral_ports_per_container
的倍数。这样可最小化CPU信息传输时的负载。示例:
--resources=ports:[31000-32000];ephemeral_ports:[32768-57344] \
--ephemeral_ports_per_container=512
容器对外的网络连接需要限速,以免单个容器占用过多带宽。可在每个容器启动时带 --egress_rate_limit_per_container
参数(单位 bytes/秒)设置速度限制,高于此限速的传输将被延迟处理,TCP协议将会增加间隔时间,降低速度,以使不掉包。
示例如下:
--egress_rate_limit_per_container=100MB
由于只能在接收到传输后根据拥堵状况再处理限速,因此,Mesos只能限制出口带宽,无法限制入口带宽。
如果所有容器都使用同一网络链路,单个容器的网络拥堵,将严重影响其他容器的网络传输。
Mesos里可以使用链路隔离来 让容器间网络传输相互间不受影响:根据容器端口范围来划定专属链路,使用FQ_Codel算法实现。使用 --egress_unique_flow_per_container
设置,示例如下:
--egress_unique_flow_per_container
下面综合网络设置命令包括:开启网络隔离,端口57345-61000给主机当临时端口,端口32768-57344给容器当临时端口,端口31000-32000给应用非临时分配,将容器出口链路设为专属,出口带宽限制为300 Mbits/second (37.5MBytes)
mesos-slave \
--isolation=network/port_mapping \
--resources=ports:[31000-32000];ephemeral_ports:[32768-57344] \
--ephemeral_ports_per_container=1024 \
--egress_rate_limit_per_container=37500KB \
--egress_unique_flow_per_container
Mesos从linux网络监测里获得的每个容器的日志存放到slave节点的/monitor/statistics.json
文件中。
容器中的网络工具里,在 statistics
下,可查看如下信息:
统计项 | 解释 | 类型 |
---|---|---|
net_rx_bytes |
收到的流量:单位 bytes | 累计 |
net_rx_dropped |
接收端的丢包数 | 累计 |
net_rx_errors |
接收端的错误数 | 累计 |
net_rx_packets |
收到的包数 | 累计 |
net_tx_bytes |
发出的流量:单位 bytes | 累计 |
net_tx_dropped |
发出端的丢包数 | 累计 |
net_tx_errors |
发送端的错误数 | 累计 |
net_tx_packets |
发出的包数 | 累计 |
另外Linux Traffic Control 可在 statistics/net_traffic_control_statistics
里采集如下信息:限速和过载。
统计项 | 解释 | 类型 |
---|---|---|
backlog |
排队待传输的字节数 [1] | 计量 |
bytes |
发出的字节数 | 累计 |
drops |
发出端的丢包数 | 累计 |
overlimits |
超限额次数,当超过限额时,每收到一包算一次。[2] | 累计 |
packets |
发出的包数 | 累计 |
qlen |
排队待传输的包数 | 计量 |
ratebps |
传输速度——每秒字节数:单位 bytes/second [3] | 计量 |
ratepps |
传输速度——每秒包数:单位 packets/second [3] | 计量 |
requeues |
因资源占用(比如 kernel locking)而导致的传输失败包数 [3] | 累计 |
[1] Backlog只在 bloat_reduction接口列出。
[2] Overlimits只在 bw_limit 接口列出。
[3] 目前都报为0。
示例:可在slave节点中,输入下面命令,获得如下的结果:
$ curl -s http://localhost:5051/monitor/statistics | python2.6 -mjson.tool
[
{
"executor_id": "job.1436298853",
"executor_name": "Command Executor (Task: job.1436298853) (Command: sh -c 'iperf ....')",
"framework_id": "20150707-195256-1740121354-5150-29801-0000",
"source": "job.1436298853",
"statistics": {
"cpus_limit": 1.1,
"cpus_nr_periods": 16314,
"cpus_nr_throttled": 16313,
"cpus_system_time_secs": 2667.06,
"cpus_throttled_time_secs": 8036.840845388,
"cpus_user_time_secs": 123.49,
"mem_anon_bytes": 8388608,
"mem_cache_bytes": 16384,
"mem_critical_pressure_counter": 0,
"mem_file_bytes": 16384,
"mem_limit_bytes": 167772160,
"mem_low_pressure_counter": 0,
"mem_mapped_file_bytes": 0,
"mem_medium_pressure_counter": 0,
"mem_rss_bytes": 8388608,
"mem_total_bytes": 9945088,
"net_rx_bytes": 10847,
"net_rx_dropped": 0,
"net_rx_errors": 0,
"net_rx_packets": 143,
"net_traffic_control_statistics": [
{
"backlog": 0,
"bytes": 163206809152,
"drops": 77147,
"id": "bw_limit",
"overlimits": 210693719,
"packets": 107941027,
"qlen": 10236,
"ratebps": 0,
"ratepps": 0,
"requeues": 0
},
{
"backlog": 15481368,
"bytes": 163206874168,
"drops": 27081494,
"id": "bloat_reduction",
"overlimits": 0,
"packets": 107941070,
"qlen": 10239,
"ratebps": 0,
"ratepps": 0,
"requeues": 0
}
],
"net_tx_bytes": 163200529816,
"net_tx_dropped": 0,
"net_tx_errors": 0,
"net_tx_packets": 107936874,
"perf": {
"duration": 0,
"timestamp": 1436298855.82807
},
"timestamp": 1436300487.41595
}
}
]