最近在研究使用Mesos,对marathon-lb和mesos-dns等诸多工具,只是停留在知道和会用的阶段,特别是对于基于marathon-lb的HAProxy的应用分组和使用更是一头雾水。现在资料也少,看了官网上的这篇文章觉得讲得还算是全面。兄弟英文水平差,先用Google翻译了一下,然后再梳理整理,同时,加上了一些自己的理解的说明。因为每个人的经历和经验都不同,以下这些东西对于有些人可能很难对于有些人可能很简单,所以不当之处还请大家多多见谅。欢迎讨论和拍砖。
这是服务发现和负载均衡系列的第一部分,共两部分。
Mesosphere Datacenter Operating System (DCOS) 为服务发现和负载均衡提供了有用的工具。其中一个主要的工具就是marathon-lb,这将是本文的重点。
在启动了DCOS集群以后,通过使用Mesos-DNS可以发现所有的task。发现是通过DNS实现的,但是有一些限制,其中包括:
- DNS无法识别服务端口,除非使用SRV查询(SRV记录它是DNS服务器的数据库中支持的一种资源记录的类型,它记录了哪台计算机提供了哪个服务这么一个简单的信息);大多数应用程序都无法使用SRV记录“开箱即用”。
- DNS不具有快速故障转移能力。
- DNS记录有一个TTL(生存时间:time to live),同时Mesos-DNS使用轮询来创建DNS记录; 这可能会导致过时的记录。
- DNS记录不提供任何服务的健康数据。
- 一些应用程序和库不正确地处理多个A记录(handle multiple A records);在某些情况下,查询可能被缓存,并根据需要不正确地重新加载。
注:A记录也称为主机记录,是使用最广泛的DNS记录,A记录的基本作用就是说明一个域名对应的IP是多少,它是域名和IP地址的对应关系,表现形式为:www.xxx.com 192.168.1.1这就是一个A记录!A记录除了进行域名IP对应以外,还有一个高级用法,可以作为低成本的负载均衡的解决方案,比如说:www.xxx.com 可以创建多个A记录,对应多台物理服务器的IP地址,可以实现基本的流量均衡!
为了解决这个问题,我们为Marahon提供一个叫做Marathon Load Balancer的工具,简称marathon-lb.
注:这句话是否意味着:使用Mesos-DNS是有局限,而marathon-lb是可以起到与Mesos-DNS同样作用的,这样的话就不需要使用Mesos-DNS?
marathon-lb是基于HAProxy(一个快速的代理服务器和负载均衡器)的。HAProxy可以为基于TCP和HTTP协议的应用提供代理和负载均衡。支持如SSL,HTTP压缩,健康检查,Lua脚本等功能。marathon-lb会将事件提交至marathon事件总线,同时实时的对HAProxy的配置进行更新和修改。
你可以可以用多种拓扑结构配置marathon-lb。以下是如何使用的marathon-lb的一些例子:
注:”edge load balancer”,我理解应该是顶级或者入口级的负载均
在本文中,我们将讨论上述第四个选项,以突出说明marathon-lb的特点。
为了演示marathon-lb,我们将启动一个部署在AWS上的DCOS集群,并运行一个内部和外部负载均衡器。外部负载均衡将用于分发由外部HTTP请求到集群,并且内部的LB将用于内部服务发现和负载平衡。由于我们是在AWS上实现,对外通讯将先做一个ELB配置用来对外暴露“public”代理节点。
如果想跟着一起操作,你可以在AWS上创建自己的集群。合在AWS上使用DCOS社区版Mesosphere不会收取任何费用,但你仍然必须支付的基本情况和相关的AWS费用。
marathon-lb提供可直接安装的包。要安装marathon-lb:
$ dcos package install marathon-lb
注:我是使用mesosphere提供的安装包,在centos7上搭建的mesos环境,然后使用marathon-lb的docker镜像。我觉得阅读本文主要是要了解marathon-lb的使用以及如何规划负载均衡,dcos的安装模式可以忽略。
要验证marathon-lb是否正常工作,根据你搭建的Mesos环境,用Mesos-slave主机的IP,访问http://:9090/haproxy?stats。你会看到这样的统计报表页面:
接下来,我们将建立我们的内部LB。要做到这一点,我们必须先指定marathon-lb中的一些配置选项。创建一个名为options.json包含以下内容:
{
"marathon-lb":{
"name":"marathon-lb-internal",
"haproxy-group":"internal",
"bind-http-https":false,
"role":""
}
}
在这个选项文件,我们需要修改 a)的应用实例的名称,b)HAProxy的组名,同时,我们停用HAProxy端口80和443的HTTP和HTTPS转发(因为它不需要)。
接下来,运行与我们的新选项安装命令:
$ dcos package install --options=options.json marathon-lb
注:在Mesos环境中,可以直接用命令执行,例如:curl -X POST http://mesos-master:8080/v2/apps -d @options.json -H “Content-type: application/json”
现在,我们将有2个负载均衡:一个外部LB和一个内部LB.让我们运行一个示例应用程序来演示功能。下面是我们的nginx的外部实例:
注:
1)以上内容中共安装了两个marathon-lb。第一个是上文中最早安装的,默认安装的marathon-lb,HAPROXY_GROUP值是external的,默认是绑定了80和443端口的。用上面的带options.json参数的命令,又安装了一个marathon-lb,这里面指定HAPROXY_GROUP为internal,同时取消对80和443的绑定。
2)这里的Nginx不是用于负载均衡,这里把Nginx当作一个服务或者一个微服务就行。可能是考虑nginx相对比较小,好配置,所以很多mesos的文章中都是用nginx做示例。
{
"id": "nginx-external",
"container": {
"type": "DOCKER",
"docker": {
"image": "nginx:1.7.7",
"network": "BRIDGE",
"portMappings": [
{ "hostPort": 0, "containerPort": 80, "servicePort": 10000 }
],
"forcePullImage":true
}
},
"instances": 1,
"cpus": 0.1,
"mem": 65,
"healthChecks": [{
"protocol": "HTTP",
"path": "/",
"portIndex": 0,
"timeoutSeconds": 10,
"gracePeriodSeconds": 10,
"intervalSeconds": 2,
"maxConsecutiveFailures": 10
}],
"labels":{
"HAPROXY_GROUP":"external"
}
}
您可以通过粘贴上面的JSON到一个文件中(称为发动DCOS这个程序nginx-external.json),并运行:
$ dcos marathon app add nginx-external.json
注:与第一个json说明的运行方式相同,直接用curl来执行。
Application(执行json就会在marathon创建一个application)的定义中,包含了用HAPROXY_GROUP作为Key的特殊标签。这个标签告诉marathon-lb是否对外暴露该应用程序。外部marathon-lb运行时设置–group参数的值为external,这是默认值。你可以在这里检查代码,如果你愿意的话。
下面是我们的内部nginx的:
{
"id": "nginx-internal",
"container": {
"type": "DOCKER",
"docker": {
"image": "nginx:1.7.7",
"network": "BRIDGE",
"portMappings": [
{ "hostPort": 0, "containerPort": 80, "servicePort": 10001 }
],
"forcePullImage":true
}
},
"instances": 1,
"cpus": 0.1,
"mem": 65,
"healthChecks": [{
"protocol": "HTTP",
"path": "/",
"portIndex": 0,
"timeoutSeconds": 10,
"gracePeriodSeconds": 10,
"intervalSeconds": 2,
"maxConsecutiveFailures": 10
}],
"labels":{
"HAPROXY_GROUP":"internal"
}
}
请注意,我们指定一个servicePort参数。servicePort端口是该服务(本例中的Ninx)在marathon-lb中的端口。默认情况下,marathon-lb保留从10000至10100的端口,用于对外的服务使用,所以你应该从10000开始使用(如果你数一下,共计101服务端口可以使用)。您可能需要使用电子表格,来跟踪记录这些端口在marathon-lb中的分配和使用情况,以及每个端口是与哪组LB的服务对应。
让我们再添加一个Nginx实例:
{
"id": "nginx-everywhere",
"container": {
"type": "DOCKER",
"docker": {
"image": "nginx:1.7.7",
"network": "BRIDGE",
"portMappings": [
{ "hostPort": 0, "containerPort": 80, "servicePort": 10002 }
],
"forcePullImage":true
}
},
"instances": 1,
"cpus": 0.1,
"mem": 65,
"healthChecks": [{
"protocol": "HTTP",
"path": "/",
"portIndex": 0,
"timeoutSeconds": 10,
"gracePeriodSeconds": 10,
"intervalSeconds": 2,
"maxConsecutiveFailures": 10
}],
"labels":{
"HAPROXY_GROUP":"external,internal"
}
}
内外部都可以方案该Nginx实例。请注意,我们已经改变了servicePort端口,因此不会与其他Nginx的情况下重叠。
可以通过使用端口映射来定义服务端口(如在上面的例子),或者在marathon application的定义中增加ports参数。
为了测试我们的配置,用SSH登录到集群中的实例(如主机)之一,并尝试curl-ing端点:
$ curl http://marathon-lb.marathon.mesos:10000/
$ curl http://marathon-lb-internal.marathon.mesos:10001/
$ curl http://marathon-lb.marathon.mesos:10002/
$ curl http://marathon-lb-internal.marathon.mesos:10002/
每一个地址都应该返回Nginx的“欢迎”页面,如下所示:
marathon-lb的一个重要特点是支持虚拟主机。这可以使您将HTTP通路分发到多个主机(FQDN的),并且将请求路由到正确的endpoint。例如,你可以有两个不同的网络地址,ilovesteak.com和steaknow.com,同时这两个地址的DNS都通过相同的端口指向同一个LB,并且将HAProxy基于域名将通信路由到正确的endpoint。
要测试虚拟主机功能,切换到AWS控制台,查看您的punblic ELB。为了进行测试,我们将对public ELB进行两处修改。
首先,我们将修改健康检查,使用HAProxy的内置的健康检查:
其次,修改健康检查的路径/_haproxy_health_check,让它去ping主机的9090端口。现在,如果你浏览到实例选项卡,您应该看到界面列出状态为InService的实例,就像这样:
现在,我们的ELB能够将流量路由到HAProxy的。接下来,让我们修改nginx的应用程序来暴露我们的服务。要做到这一点,你需要从Description tab页面中找到ELB public DNS的名称。在这个例子中,我的public DNS名字是brenden-j-PublicSl-1LTLKZEH6B2G6-1145355943.us-west-2.elb.amazonaws.com。
现在我将修改外部nginx的应用是这样的:
{
"id": "nginx-external",
"container": {
"type": "DOCKER",
"docker": {
"image": "nginx:1.7.7",
"network": "BRIDGE",
"portMappings": [
{ "hostPort": 0, "containerPort": 80, "servicePort": 10000 }
],
"forcePullImage":true
}
},
"instances": 1,
"cpus": 0.1,
"mem": 65,
"healthChecks": [{
"protocol": "HTTP",
"path": "/",
"portIndex": 0,
"timeoutSeconds": 10,
"gracePeriodSeconds": 10,
"intervalSeconds": 2,
"maxConsecutiveFailures": 10
}],
"labels":{
"HAPROXY_GROUP":"external",
"HAPROXY_0_VHOST":"brenden-j-PublicSl-1LTLKZEH6B2G6-1145355943.us-west-2.elb.amazonaws.com"
}
}
我们已经添加了标签HAPROXY_0_VHOST,它告诉marathon-lb就用虚拟主机的外部负载均衡来暴露Nginx的访问。在labels中,包含0的Key与servicePort定义对应 ,从0开始。如果你有多个servicePort定义,你会遍历它们作为0,1,2,依此类推。
现在,如果你浏览到在浏览器中ELB的公共DNS地址,您应该看到以下内容:
当当!
注:原文是“Ta-da!”,语气词而已,不是当当网
在第二部分中,在这里我们谈论更多marathon-lb的高级功能,以及如何使用HAProxy的实现应用程序autoscaling。
本文更多的是在讲解如何来使用marathon-lb,以及在marathon-lb中,如何对HAProxy进行分组。讲得还是比较浅,特别是没有说明marathon-lb自动增加节点进行负载均衡没有说明。我本人搭的环境中,marathon-lb是可以进行自动负载均衡的,例如:关闭一个Nginx容器,marathon-lb会根据scaling(就是下一部分要说的)的值,自动创建一个Nginx镜像。但是,组合internal和external的情况,还没有成功。等试验成功,再补充进来。
参考资料:
[1]: https://mesosphere.com/blog/2015/12/04/dcos-marathon-lb/
[2]: http://blog.chinaunix.net/uid-23241716-id-134106.html
[3]: http://bbs.51cto.com/thread-909189-1.html