Docker1.0 项目

背景

由于历史的原因我们的机器目前还是单机或单集群对应一个业务模块的形式,优势应对爆发式增长扩容方便,成本结算简单。但是随着网民的饱和,相同业务模块下移动流量上涨,PC流量直线下降,很多业务出现了低负载情况,海量服务器运维中只要有1%的低负载(既机器利用率不饱和)规模也是惊人的,在实际运营中低负载+长尾模块机器数量可能达到了25%-30%之间,当然这里也包含业务对流量做了冗余与灾备,但是多个业务模块的灾备就会出现浪费资源的情况。我们从运营中发现了这问题的存在,而运维的核心价值也是通过技术优化,能在(成本、质量、效率与安全)四块做优化达到一个很好的收益,所以从2014年中我们开始做离线业务部署项目。项目的思路是通过高负载业务(离线计算)与低负载业务进行混合部署,提升低负载机器利用率同时逐步下线高负载业务的机器为部门节约机器成本。不过经过半年多的运营中我们也发现了很多问题,离线业务的负载均衡权重统一,但是混合部署后的机器负载不均有高有低,混部的结果经常会导致部分机器高负载影响业务,可以看出这里缺少监控负载的和业务合理的手段,经常导致高负载业务影响低负载业务,接口超时影响用户的情况,这是我们不希望看到的,所以总结经验教训,在2015年上半年我们重新打磨项目开发了离线业务混合部署(琥珀自动调度系统)项目,新项目与老项目相比通过docker技术将混部业务控制在容器中,消除争抢资源对业务影响,同时对容器流量进行根据负载调度,在此基础上实现了分时调度等功能。

负载调度演示(图1)

希望通过技术架构优化与升级来充分扎干硬件资源,为公司节约服务器成本。在开发过程中,相关业务也向我们提出了以下需求(已经实现功能见图2):

  • 机器主动与被动下线不影响在线业务;
  • 可以方便的查看到系统运行状态;
  • 可以连接到容器内部查询日志以及debug程序;
  • 沉淀各系统日常数据,并根据沉淀的数据进行戳峰调度。 Web功能展示(图2)

系统访问逻辑及接入方式

根据系统需求,最终访问逻辑分为三部分(用户接入、程序逻辑、和容器生成),每层之前交互通过接口,尽量把复杂的逻辑对上一层透明,见图3。

琥珀访问逻辑图(图3)

琥珀系统提供两种接入方式:

方式1:

通过vip方式接入(推荐),用户不必关心底层系统。首次接入将业务环境打为docker,并测试。后续业务流量通过vip引入计算集群(注:计算集群与首次docker业务环境一致),用户不必关系集群内部机器数量与机器状态,系统保证相应的计算量已经容灾调度。见图4

接入访问逻辑1,图4

方式2:

业务流量通过接口获取动态IP列表,并将流量下发到列表IP中。当机器下线接口主动通知业务流量踢IP。与方式1同样首次接入需要打docker镜像源。见图5

接入访问逻辑2,图5

系统架构

我们通过介绍开源软件(docker + haproxy + confd + etcd+ clip)来完整整个琥珀系统的架构,见图6

琥珀架构图(图6)

其中开源软件(docker + haproxy + confd + etcd+ clip)介绍如下:如下:

etcd是由CoreOS开发并维护使用Go语言编写,并通过Raft一致性算法处理日志复制以保证强一致性。目前很多大项目都使用了etcd,如:Google的Kubernetes、Pivotal的Cloud Foundry、Mailgun、Apache Mesos与Mesosphere的DCOS。除开这些大型项目,在GitHub上还有超过500个项目使用了etcd;

Clip是(cmdb + tools)( http://blog.puppeter.com/read.php?7 )的结合,它将传统的对IP管理维度替换为String维度,其中String格式为(机房-产品-模块-组-端口),通过Clip可以对IP进行打标签,并根据便签对应属性形式区分服务来源。

程序安装

1)HAproxy安装

1
2
3
# wget http://www.haproxy.org/download/1.5/src/haproxy-1.5.14.tar.gz
# tar –xvzf haproxy-1.5.14.tar.gz && cd haproxy-1.5.14
# make install

HAproxy源码编译安装,启动和关闭建议采用以下方式。

1
2
3
4
# 启动
$ haproxy -f /etc/haproxy/haproxy.cfg -p /tmp/haproxy.pid
# 热重启
$ haproxy -D -f /etc/haproxy/haproxy.cfg -p /tmp/haproxy.pid -sf $(cat /tmp/haproxy.pid)

HAproxy 二进制命令参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-d 前台,debug模式
-D daemon模式启动
-q 安静模式,不输出信息
-V 详细模式
-c 对配置文件进行语法检查
-s 显示统计数据
-l 显示详细统计数据
-dk 不使用kqueue
-ds 不使用speculative epoll
-de 不使用epoll
-dp 不使用poll
-db 禁用后台模式,程序跑在前台
-sf 程序启动后向pidlist里的进程发送FINISH信号,这个参数放在命令行的最后
-st 程序启动后向pidlist里的进程发送TERMINATE信号,这个参数放在命令行的最后

HAproxy优化(HA为负载均衡,通常会产生大量的time_wait,通过对系统优化尽量降低time_wait对系统影响)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 80000
net.core.somaxconn = 32768
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 20
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.core.netdev_max_backlog = 32768
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_retries2 = 5
net.ipv4.tcp_mem = 41943040 73400320 94371840
net.ipv4.tcp_max_orphans = 3276800
fs.file-max = 1300000
  1. confd安装
    Confd的用途是监听etcd中键值变化,并根据变化更新模块中的数据。(注:这里confd 需要安装在HAproxy相同机器)
    1
    2
    3
    4
    5
    6
    wget https://github.com/kelseyhightower/confd/releases/download/v0.6.3/confd-0.6.3-linux-amd64  

    # mv confd /usr/local/bin/confd
    # chmod +x /usr/local/bin/confd
    # /usr/local/bin/confd -version
    # mkdir /etc/confd/{conf.d templates}

在conf.d目录中创建haproxy.toml文件。haproxy.toml是confd的配置文件,其作用是当etcd中的数据发生变化,根据haproxy.toml中的(src)模板信息重新生成目标(dest) 模板,最后重新加目标程序配置文件。它支持所有带配置文件的软件,譬如(nginx,apache,haproxy,lighttpd)等。以下为haproxy.toml文件内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
haproxy.toml
[template]
src = "haproxy.cfg.tmpl"
dest = "/etc/haproxy/haproxy.cfg"
keys = ["/app/servers/"]
reload_cmd = "/usr/local/services/hupo/haproxy-1.4.21/haproxy_reload"
在templates目录中创建haproxy.cfg.tmpl文件,内容如下:
global
maxconn 2000
uid 99
gid 99
daemon
nbproc 10
#debug
#quiet
defaults
retries 3
option redispatch
maxconn 10000
contimeout 5000
clitimeout 50000
srvtimeout 50000
# stats uri /haproxy-admin
listen admin_stat 0.0.0.0:8080
mode http
stats refresh 70s
stats uri /admin_stats
listen tcp-in 0.0.0.0:1991
mode tcp
balance roundrobin
{{range gets "/app/servers/*"}}
server {{base .Key}} {{.Value}} check inter 5000 fall 1 rise 2
{{end}}

3) etcd安装

1
2
3
4
# wget https://github.com/coreos/etcd/releases/download/v0.4.6/etcd-v0.4.6-linux-amd64.tar.gz
# tar -zxvf etcd-v0.4.6-linux-amd64.tar.gz
# cd etcd-v0.4.6-linux-amd64
# cp etcd* /bin/

启动

1
# etcd  -name ip_data   -addr IP:4001 -data-dir 数据文件地址 -bind-addr IP:4001

其中etcd常用参数如下:

1
2
3
4
-name:节点名称;
-addr : 客户端连接地址与端口;
-data-dir: 数据文件存储地址;
-bind-addr:绑定IP + 端口;

例子:

其中RESET-API例子

1
2
$ curl -L -X PUT http://127.0.0.1:4001/v2/keys/message -d value="Hello"
{"action":"set","node":{"key":"/message","value":"Hello","modifiedIndex":4,"createdIndex":4}}

1
2
curl -L http://127.0.0.1:4001/v2/keys/message
{"action":"get","node":{"key":"/message","value":"Hello","modifiedIndex":4,"createdIndex":4}}

1
2
$ curl -L -X DELETE http://127.0.0.1:4001/v2/keys/message
{"action":"delete","node":{"key":"/message","modifiedIndex":19,"createdIndex":4}}

关于etcd更多信息见:https://coreos.com/docs/distributed-configuration/getting-started-with-etcd/