随着近几年微服务与云计算的飞速发展,机器由物理机逐步变为了虚拟机,应用服务由庞大的单体应用逐渐变为了若干个微服务联合组成的应用集群,更新迭代的速度成倍上涨,传统的部署模式已没法知足开发平常更新需求,须要一套适合微服务的管理架构。nginx
技术栈及文档git
资源调度框架 MESOSgithub
应用编排平台 Marathonspring
nginx 动态修改 upstream dyupsdocker
nginx 动态修改 upstream upsyncapache
使用Mesos 进行机器资源管理后端
首先,是机器资源的管理。在微服务的架构中,原有的单体服务被拆分红了一个个独立单元的应用程序,这些服务体量较小,能够独立运行在配置较小的机器上。为了故障隔离,咱们会尽量的把这些服务部署在不一样的虚拟机上,这样机器的数量会成倍增长。对于运维来讲,每一个新服务部署时,须要先查看现有机器的剩余资源是否知足新服务的需求,有时可能由于评估不许确形成来回扩容、迁移,或者资源浪费。springboot
开始时,咱们的架构可能时这样的服务器
为了解决上面的问题,可使用 MESOS ( 布式资源管理框架),它能够 让咱们像用一台电脑(一个资源池)同样使用整个数据中心。
mesos 部署时分为 master 和 agent 两个角色,固然,你能够在同一台机器启动它们。架构
安装Mesos 前须要安装zookeeper,mesos 使用zk 实现高可用和选举,包括一个 master leader 和 几个备份 master 避免宕机。
Mesos master 负责管理各个Framework和Slave,并将Slave上的资源非配给各个Framework。
Mesos agent 负责管理本节点上的各个Mesos Task,为各个Executor分配资源 (低版本为 mesos-slave)。
$ cat > /tmp/bintray-mesos-el.repo <<EOF
[bintray-mesos-el]
name=bintray-mesos-el
baseurl=https://dl.bintray.com/apache...
gpgcheck=0
repo_gpgcheck=0
enabled=1
EOF
$ sudo mv /tmp/bintray-mesos-el.repo /etc/yum.repos.d/bintray-mesos-el.repo
$ sudo yum update
$ sudo yum install mesos
$ tree /etc/mesos-master
/etc/mesos-master/
|-- hostname
|-- ip
|-- log_dir
|-- quorum # quorum > (number of masters)/2
`-- work_dir
$ tree /etc/mesos-agent
/etc/mesos-agent/
|-- containerizers # 容器类型,默认 mesos,能够添加 docker,如: mesos,docker
|-- hostname
|-- ip
|-- log_dir
|-- master # master 地址,格式为 host:port 或
zk://host1:port1,host2:port2,.../path 或 file:///path/to/file
|-- resources # 设置总资源大小,能够设置小些来预留更多机器资源
`-- work_dir
$ cat /etc/mesos/zk # 设置 mesos 在zk 中的存储目录
zk://192.168.100.9:2181,192.168.100.110:2181,192.168.100.234:2181/mesos
$ systemctl start mesos-master
$ systemctl start mesos-slave
当mesos服务启动后,agent 会向master 节点汇报机器资源,包括CPU、内存、磁盘等。 当咱们要发布一个服务时,只须要设置这个服务的CPU、内存、磁盘参数, mesos master 会自动帮咱们选择有足够资源的机器去运行,以下图
咱们将微服务的启动都交给 Mesos 管理,这样咱们只须要关注总体资源便可。MESOS 提 供了UI界面,能够直接访问 mesos master 的5050 端口,查看集群资源使用状况。 整体使用状况 及 Agent 节点使用状况
完成以上后,咱们的架构变成了这样
使用Marathon 进行微服务管理
Marathon 是创建在 Mesos 上的私有 PaaS平台。它能自动处理硬件或者软件故障,并确 保每一个应用程序都"永远在线"。 咱们使用 Marathon 管理微服务有如下优点 1. 支持容器和非容器,不受限于服务启动类型,操做系统版本等。 2. 漂亮而强大的用户界面,能够在UI 上进行快捷方便的应用程序配置 3. 支持约束条件,例如容许一个mesos agent 节点只运行一个应用程序。 4. 支持健康检查。能够配置 http、https、tcp、command 类型的监控检查。 5. 完整的REST API,易于集成和编写脚本。这个对于后期集成来讲相当重要。
$ sudo rpm -Uvh http://repos.mesosphere.com/e...
$ sudo yum -y install mesos marathon
$ cat /etc/default/marathon
MARATHON_MESOS_USER="root"
MARATHON_MASTER="zk://192.168.100.9:2181,192.168.100.110:2181,192.168.100.234:2181/mesos"
MARATHON_ZK="zk://192.168.200.9:1181,192.168.100.110:2181,192.168.100.234:2181/marathon"
systemctl start marathon
启动后,直接访问 marathon 的 8080 端口,就能看到一个漂亮强大的 UI 界面。
咱们以 springboot 应用为例,在 marathon 上建立一个应用程序
当咱们更新应用程序时, marathon 会新建相同实例数量的应用程序,待 health check 经过以后替换老节点,因此不须要担忧新的服务没有启动期间老的服务停掉形成线上事 故。 到这里为止,咱们已经能够在marathon 上方便快捷的进行平常应用的建立、升级、扩 容、缩容。当服务健康检查失败或者机器宕机后,marathon 会自动在其它节点上启动挂掉的应用程序,大大提高了高可用性。
使用 nginx upsync/dyups 模块进行平滑变动
当咱们的微服务能够随机分配在不一样机器上时,便产生了一个新的使人头疼的问题。 nginx 并不知道后端节点的变动, 也不可能每次都去手动修改 upstream 节点, reload nginx,这样成本就过高了。 咱们的解决思路是和微服务的注册中心打通,当服务注册、注销时,都会对注册中心进行 更新,利用 nginx upsync/dyups 模块 能够动态修改 upstream 节点的能力进行同步,作 到平滑变动。 若是使用的注册中心为 consul,建议使用 upsync 模块,这样无需开发,只须要简单的 nginx 配置,就能够实现咱们想要的效果, 支持 consul kv, consul_services, consul_health, 同时 upsync 也支持 etcd。建议使用 consul_health 接口。 upsync 模块不是nginx 内置模块,使用时须要从新编译添加此模块。
wget 'http://nginx.org/download/ngi...'
tar -xzvf nginx-1.8.0.tar.gz
cd nginx-1.8.0/
./configure --add-module=/path/to/nginx-upsync-module
make
make install
配置文件示例
http {
upstream test {
upsync 127.0.0.1:8500/v1/health/service/test upsync_timeout=6m upsync_interval=500ms upsync_type=consul_health strong_dependency=off;
upsync_dump_path /usr/local/nginx/conf/servers/servers_test.conf;
include /usr/local/nginx/conf/servers/servers_test.conf;
}
upstream bar {
server 127.0.0.1:8090 weight=1 fail_timeout=10 max_fails=3;
}
server {
listen 8080;
location = /proxy_test {
proxy_pass http://test;
}
location = /bar {
proxy_pass http://bar;
}
location = /upstream_show {
upstream_show;
}
}
}
当upsync没法知足咱们的需求或者注册中心不是 consul、etcd 时,咱们能够考虑使用 nginx dyups 模块。dyups 仅对外提供 upstream 的增删查改接口,和注册中心对比、修 改的工做须要咱们经过脚本的方式完成。虽然这种方式麻烦一些,可是可定制化程度高, 支持 http, C,lua API,基本上能够知足大部分的场景需求。
dyups 模块也须要nginx 编译时添加
$ git clone git://github.com/yzprofile/ngx_http_dyups_module.git
$ ./configure --add-module=./ngx_http_dyups_module
$ ./configure --add-dynamic-module=./ngx_http_dyups_module
示例配置
http {
include conf/upstream.conf;
server {
listen 8080;
location / {
# The upstream here must be a nginx variable
proxy_pass http://$dyups_host;
}
}
server {
listen 8088;
location / {
return 200 "8088";
}
}
server {
listen 8089;
location / {
return 200 "8089";
}
}
server {
listen 8081;
location / {
dyups_interface;
}
}
}
特别注意,使用dyups 时, proxy_pass 时的 upstream 必须是 nginx 变量,不然不生 效,切记。
总体回顾
通过以上调整,咱们获得了如下优化