参考文档:html
mesosphere社区版:https://github.com/mesosphere/open-docsnode
mesosphere仓库:https://github.com/mesosphere/open-docs/blob/master/downloads/mesos.mdpython
marathon: https://mesosphere.github.io/marathon/docs/mysql
chronos: https://mesos.github.io/chronos/docs/linux
consul:https://www.consul.io/ https://releases.hashicorp.com/consul/nginx
docker安装:https://docs.docker.com/engine/installation/linux/docker-ce/centos/git
mesos 集群资源管理框架(以集群的形式出现,主决定资源的分配,从负责执行executor),分配资源,提供offer给framework,不负责调度资源,千言万语都在这里了mesos的设计结构。github
marathon 是mesos的framework,容器编排系统,保证长时间的运行任务,相似后台执行或者supervisor。web
zooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置管理维护、域名服务、分布式同步、组服务、健康检查,HA等。
Chronos是一个运行在Mesos之上的具备分布式容错特性的做业调度器。在Airbnb公司,它是cron的替代品。与cron相比,Chronos在不少方面具有优点。好比,它支持ISO8601标准,容许更灵活地定义调度时间;Chronos也支持任务依赖,即一个做业的开始依赖于一些任务的完成,和marathon同样都是遵从mesos的指令,给mesos搬砖的。
consul常常拿来和etcd、 zookeeper来对比,他有和etcd同样的服务发现、服务注册功能,也有和etcd、zookeeper同样的配置存储功能,详细的对比在此再也不列出。
Registrator是一个独立于服务注册表的自动服务注册/注销组件,通常以容器的方式进行部署。会自动侦测它所在的宿主机上的全部 容器状态(启用/销毁),并根据容器状态到对应的服务注册列表注册/注销服务。去除了须要手动管理Consul服务条目的复杂性,它监视容器的启动和中止,根据容器暴露的端口和环境变量自动注册服务。
事实上, 经过读取同一台宿主机的其余容器 的环境变量进行服务注册、健康检查定义等操做,支持可插拔式的服务注册表配置。
架构图看起来像这样:
mesos架构:
架构图能够看出mesos主要两部分主和从 ,主集群依靠zookeeper
架构图展现了Mesos的重要组成部分,Mesos由一个master进程管理运行着每一个客户端节点的slave进程和跑任务的Mesos计算框架。
Mesos进程经过计算框架能够很细致的管理cpu和内存等,从而提供资源。每一个资源提供都包含了一个清单(slave ID,resource1:amount1,resource2,amount2,…)master会根据现有的资源决定提供每一个计算框架多少资源。例如公平分享或者根据优先级分享。
为了支持不一样种的政策,master经过插件机制新增额一个allocation模块使之分配资源更简单方便。
一个计算框架运行在两个组建之上,一个是Scheduler,他是master提供资源的注册中心,另外一个是Executor程序,用来发起在slave节点上运行计算框架的任务。master决定给每一个计算框架提供多少计算资源,计算框架的调度去选择使用哪一种资源。当一个计算框架接受了提供的资源,他会经过Mesos的任务描述运行程序。Mesos也会在相应的slave上发起任务。
Mesos是Apache下的开源分布式资源管理框架,它被称为分布式系统的内核。Mesos最初是由加州大学伯克利分校的AMPLab开发,后在Twitter获得普遍使用。
Mesos-Master:主要负责管理各个framework和slave,并将slave上的资源分配给各个framework。
Mesos-Slave:负责管理本节点上的各个mesos-task,好比:为各个executor分配资源。
Framework:计算框架,如:Hadoop、Spark、Kafaka、ElasticSerach等,经过MesosSchedulerDiver接入Mesos
Executor:执行器,就是安装到每一个机器节点的软件,这里就是利用docker的容器来担任执行器的角色。具备启动销毁快,隔离性高,环境一致等特色。
Mesos-Master是整个系统的核心,负责管理接入Mesos的各个framework(由frameworks_manager管理)和slave(由slaves_manager管理),并将slave上的资源按照某种策略分配给framework(由独立插拔模块Allocator管理)。
Mesos-Slave负责接受并执行来自Mesos-master的命令、管理节点上的mesos-task,并为各个task分配资源。Mesos-slave将本身的资源量发送给mesos-master,由mesos-master中的Allocator模块决定将资源分配给哪一个framework,当前考虑的资源有CPU和内存两种,也就是说,Mesos-slave会将CPU个数的内存量发送给mesos-master,而用户提交做业时,须要指定每一个任务须要的CPU个数和内存。这样:当任务运行时,mesos-slave会将任务放导包含固定资源Linux container中运行,以达到资源隔离的效果。很明显,master存在单点故障问题,为此:Mesos采用了Zookeeper解决该问题。
Framework是指外部的计算框架,若是Hadoop、Mesos等,这些计算框架可经过注册的方式接入Mesos,以便Mesos进行统一管理和资源分配。Mesos要求可接入的框架必须有一个调度模块,该调度器负责框架内部的任务调度。当一个framework想要接入Mesos时,须要修改本身的调度器,以便向Mesos注册,并获取Mesos分配给本身的资源,这样再由本身的调度器将这些资源分配给框架中的任务,也就是说,整个Mesos系统采用了双层调度框架:第一层,由Mesos将资源分配给框架。第二层,框架本身的调度器将资源分配给本身内部的任务。当前Mesos支持三中语言编写的调度器,分别是C++、Java、Python。为了向各类调度器提供统一的接入方式,Mesos内部采用C++实现了一个MesosSchedulerDriver(调度驱动器),framework的调度器可调用该driver中的接口与Mesos-master交互,完成一系列功能(如注册,资源分配等。)
Executor主要用于启动框架内部的task。因为不一样的框架,启动task的接口或者方式不一样,当一个新的框架要接入mesos时,须要编写一个Executor,告诉Mesos如何启动该框架中的task。为了向各类框架提供统一的执行器编写方式,Mesos内部采用C++实现了一个MesosExecutorDiver(执行器驱动器),framework可经过该驱动器的相关接口告诉Mesos启动task的方式。
mesos运行流程:
流程步骤:
一、slave1报告给master他拥有4核cpu和4G剩余内存,Marathon调用allocation政策模块,告诉slave1计算框架1应该被提供可用的资源。
二、master给计算框架1发送一个在slave上可用的资源描述。
三、计算框架的调度器回复给master运行在slave上两个任务相关信息,任务1须要使用2个CPU,内存1G,任务2需使用1个CPU,2G内存。
四、最后,master发送任务给slave,分配适当的给计算框架执行器,继续发起两个任务(图1.1-2虚线处),由于任有1个CPU和1G内存未分配,allocation模块如今或许提供剩下的资源给计算框架2。
除此以外,当任务完成,新的资源成为空闲时,这个资源提供程序将会重复。
说明:
主机名 |
IP |
OS |
安装服务 |
mesos-master1 |
192.168.8.131 |
CentOS-7.5 |
mesos-master, marathon,zookeeper, consul-server, chronos, consul-template |
mesos-master2 |
192.168.8.132 |
CentOS-7.5 |
mesos-master, marathon,zookeeper, consul-server, chronos |
mesos-master3 |
192.168.8.133 |
CentOS-7.5 |
mesos-master, marathon,zookeeper, consul-server, chronos |
mesos-slave1 |
192.168.8.134 |
CentOS-7.5 |
mesos-slave, docker, registrator |
mesos-slave2 |
192.168.8.135 |
CentOS-7.5 |
mesos-slave, docker, registrator |
软件版本:
服务 |
版本 |
做用 |
zookeeper |
3.4.12 |
保持各master之间的通讯,选举leader、HA |
mesos-master |
1.6.0 |
管理接入mesos的各个framework & slave,并将slave上的资源按照相应策略分配给framework |
mesos-slave |
1.6.0 |
任务执行节点 |
marathon |
1.6.352 |
调度器,用于下发任务,可保持长应用 |
docker |
1.13.1 |
具体执行docker下发任务 |
chronos |
3.0+ |
cron-on-mesos,用来运行基于容器的定时任务的Mesos框架 |
consul/ registrator |
1.1.0/ latest |
提供服务自动注册、发现功能 |
consul-template |
0.19.4 |
Consul template 搭配consul使用,支持多种负载均衡接入层,如Nginx、Haproxy,LVS |
以节点zk-node1为例,zk-node2/3根据状况调整。
# systemctl stop firewalld
# setenforce 0
# systemctl disable firewalld
# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.8.131 mesos-master1
192.168.8.132 mesos-master2
192.168.8.133 mesos-master3
192.168.8.134 mesos-slave1
192.168.8.135 mesos-slave2
# yum groupinstall -y "Development Tools"
# yum install -y tar wget git lrzsz lsof
ZooKeeper运行在java环境下,文档中建议安装jdk 1.7以上版本(含)。
# yum -y install java java-devel
# java -version
openjdk version "1.8.0_171"
OpenJDK Runtime Environment (build 1.8.0_171-b10)
OpenJDK 64-Bit Server VM (build 25.171-b10, mixed mode)
# tar xf zookeeper-3.4.12.tar.gz -C /usr/local
# chown -R root.root /usr/local/zookeeper-3.4.12
# ln -s /usr/local/zookeeper-3.4.12/ /usr/local/zk
# cp /usr/local/zk/conf/zoo_sample.cfg /usr/local/zk/conf/zoo.cfg
zookeeper配置文件详解:
下面就是zoo.cfg配置文件的修改了,那么咱们首先要熟悉下zookeeper配置文件。
# cat /usr/local/zk/conf/zoo.cfg
dataDir:数据目录
dataLogDir:日志目录
clientPort:客户端链接端口
tickTime:Zookeeper 服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每隔tickTime 时间就会发送一个心跳。
initLimit:Zookeeper的Leader 接受客户端(Follower)初始化链接时最长能忍受多少个心跳时间间隔数。当已经超过 5个心跳的时间(也就是tickTime)长度后 Zookeeper 服务器尚未收到客户端的返回信息,那么代表这个客户端链接失败。总的时间长度就是 5*2000=10 秒
syncLimit:表示 Leader 与 Follower 之间发送消息时请求和应答时间长度,最长不能超过多少个tickTime 的时间长度,总的时间长度就是 2*2000=4 秒。
server.A=B:C:D:
A 是一个数字,表示这个是第几号服务器;
B 是这个服务器的 ip 地址;
C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;
D 表示的是万一集群中的 Leader 服务器挂了,须要一个端口来从新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通讯的端口。
# grep -Ev "#|^$" /usr/local/zk/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zk/data/zk1
dataLogDir=/usr/local/zk/logs
clientPort=2181
maxClientCnxns=60
server.1=192.168.8.131:2888:3888
server.2=192.168.8.132:2888:3888
server.3=192.168.8.133:2888:3888
# mkdir /usr/local/zk/data/zk1 -p
# mkdir /usr/local/zk/logs -p
# echo "1" > /usr/local/zk/data/zk1/myid
# scp -p /usr/local/zk/conf/zoo.cfg root@192.168.8.132:/usr/local/zk/conf/zoo.cfg
# scp -p /usr/local/zk/conf/zoo.cfg root@192.168.8.133:/usr/local/zk/conf/zoo.cfg
# mesos-master2的zk配置,一样须要建立dataDir,dataLogDir目录和myid文件,文件内容2
# sed -i 's/zk1/zk2/g' /usr/local/zk/conf/zoo.cfg
# mkdir /usr/local/zk/data/zk2 -p
# mkdir /usr/local/zk/logs -p
# echo "2" > /usr/local/zk/data/zk2/myid
# grep -Ev "#|^$" /usr/local/zk/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zk/data/zk2
dataLogDir=/usr/local/zk/logs
clientPort=2181
maxClientCnxns=60
server.1=192.168.8.131:2888:3888
server.2=192.168.8.132:2888:3888
server.3=192.168.8.133:2888:3888
# mesos-master3的zk配置,一样须要建立dataDir,dataLogDir目录和myid文件,文件内容3
# sed -i 's/zk1/zk3/g' /usr/local/zk/conf/zoo.cfg
# mkdir /usr/local/zk/data/zk3 -p
# mkdir /usr/local/zk/logs -p
# echo "3" > /usr/local/zk/data/zk3/myid
# grep -Ev "#|^$" /usr/local/zk/conf/zoo.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/usr/local/zk/data/zk3
dataLogDir=/usr/local/zk/logs
clientPort=2181
maxClientCnxns=60
server.1=192.168.8.131:2888:3888
server.2=192.168.8.132:2888:3888
server.3=192.168.8.133:2888:3888
启动zk服务,查看状态:
# /usr/local/zk/bin/zkServer.sh start
# /usr/local/zk/bin/zkServer.sh status
zk集群各节点状态:
zk各节点端口:
因而可知,集群已经正常运行。
客户端能够经过nc或telnet链接ZooKeeper Server提交指令。
ZooKeeper Client 简单操做:
9个基本操做指令:
Mesos 集群部署
Mesos集群有MesosMaster和Mesos Slave两个角色。
mesosphere仓库
须要在Mesos Master和MesosSlave节点均安装。
# 添加mesosphere repository,根据github mesosphere社区版获取最新repository
# rpm -Uvh http://repos.mesosphere.io/el/7/noarch/RPMS/mesosphere-el-repo-7-2.noarch.rpm
# hostnamectl --static set-hostname mesos-master1 //修改主机名
# yum -y install mesos marathon
mesos-master增长zookeeper配置,选主并增长HA:
# vi /etc/mesos/zk
zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/mesos
# scp /etc/mesos/zk root@192.168.8.132:/etc/mesos/zk
# scp /etc/mesos/zk root@192.168.8.133:/etc/mesos/zk
设置文件/etc/master-/quorum内容为一个大于(master节点数除以2)的整数。即采用四舍五入,好比这里有3个master节点,那么3/2=1.5,四舍五入为2。
# echo "2" >/etc/mesos-master/quorum
# cat /etc/mesos-master/quorum
2
# scp /etc/mesos-master/quorum root@192.168.8.132:/etc/mesos-master/quorum
# scp /etc/mesos-master/quorum root@192.168.8.133:/etc/mesos-master/quorum
#
主机名和ip要在hosts中写入,最好不要使用localhost,不然会出现slave不能识别,以及marathon任务下发不正常等现象。
# 默认marathon无相关配置目录/文件
# mkdir -p /etc/marathon/conf
mesos-master1:
# echo "192.168.8.131" >/etc/mesos-master/hostname
# echo "192.168.8.131" >/etc/mesos-master/ip
# echo "192.168.8.131" >/etc/marathon/conf/hostname
# echo "192.168.8.131" >/etc/marathon/conf/ip
mesos-master2:
# echo "192.168.8.132" >/etc/mesos-master/hostname
# echo "192.168.8.132" >/etc/mesos-master/ip
# echo "192.168.8.132" >/etc/marathon/conf/hostname
# echo "192.168.8.132" >/etc/marathon/conf/ip
mesos-master3:
# echo "192.168.8.133" >/etc/mesos-master/hostname
# echo "192.168.8.133" >/etc/mesos-master/ip
# echo "192.168.8.133" >/etc/marathon/conf/hostname
# echo "192.168.8.133" >/etc/marathon/conf/ip
marathon链接mesos-master及HA:
# cp /etc/mesos/zk /etc/marathon/conf/master
# cp /etc/mesos/zk /etc/marathon/conf/zk
# sed -i 's|mesos|marathon|g' /etc/marathon/conf/zk
# cat /etc/marathon/conf/master
zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/mesos
# cat /etc/marathon/conf/zk
zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/marathon
# scp /etc/marathon/conf/master root@192.168.8.132:/etc/marathon/conf/
# scp /etc/marathon/conf/master root@192.168.8.133:/etc/marathon/conf/
# scp /etc/marathon/conf/zk root@192.168.8.132:/etc/marathon/conf/
# scp /etc/marathon/conf/zk root@192.168.8.133:/etc/marathon/conf/
# systemctl enable mesos-master marathon
# systemctl start mesos-master marathon
# systemctl disable mesos-slave
# systemctl status mesos-master marathon
# systemctl status marathon #marathon启动报错
● marathon.service - Scheduler for Apache Mesos
Loaded: loaded (/usr/lib/systemd/system/marathon.service; enabled; vendor preset: disabled)
Active: activating (auto-restart) (Result: exit-code) since Mon 2018-05-14 21:13:32 CST; 37s ago
Process: 25368 ExecStart=/usr/share/marathon/bin/marathon (code=exited, status=1/FAILURE)
……
Main PID: 25368 (code=exited, status=1/FAILURE)
May 14 21:13:32 mesos-master1 systemd[1]: marathon.service: main process exited, code=exited, status=1...LURE
……
Hint: Some lines were ellipsized, use -l to show in full.
用如下命令 [journalctl -o verbose _PID=24962] 查看marathon进程的详细信息。
# journalctl -o verbose _PID=25368
-- Logs begin at Sun 2018-05-13 03:47:48 CST, end at Mon 2018-05-14 21:08:12 CST. --
Mon 2018-05-14 21:07:04.849490 CST [s=2f8e0393e2dc4d639f4d5bf76a4e9b6f;i=ec5;b=4a9ee33c3e074eb987230b0202c47a
PRIORITY=6
_SYSTEMD_SLICE=system.slice
_BOOT_ID=4a9ee33c3e074eb987230b0202c47a39
_MACHINE_ID=74bb4614536844d798b123d0cc927d4e
SYSLOG_FACILITY=3
_TRANSPORT=stdout
_SELINUX_CONTEXT=system_u:system_r:init_t:s0
_EXE=/usr/bin/bash
_CAP_EFFECTIVE=0
_COMM=bash
_HOSTNAME=mesos-master1
SYSLOG_IDENTIFIER=marathon
MESSAGE=No start hook file found ($HOOK_MARATHON_START). Proceeding with the start script.
_UID=998
_GID=996
_CMDLINE=bash /usr/share/marathon/bin/marathon
_SYSTEMD_CGROUP=/system.slice/marathon.service
_SYSTEMD_UNIT=marathon.service
_STREAM_ID=bd3ee42018a94236baeab1e5f653171f
_PID=24962
Mon 2018-05-14 21:07:08.496043 CST [s=2f8e0393e2dc4d639f4d5bf76a4e9b6f;i=ec6;b=4a9ee33c3e074eb987230b0202c47a
PRIORITY=6
_SYSTEMD_SLICE=system.slice
_BOOT_ID=4a9ee33c3e074eb987230b0202c47a39
_MACHINE_ID=74bb4614536844d798b123d0cc927d4e
SYSLOG_FACILITY=3
_TRANSPORT=stdout
_SELINUX_CONTEXT=system_u:system_r:init_t:s0
_CAP_EFFECTIVE=0
_HOSTNAME=mesos-master1
SYSLOG_IDENTIFIER=marathon
_UID=998
_GID=996
_SYSTEMD_CGROUP=/system.slice/marathon.service
_SYSTEMD_UNIT=marathon.service
MESSAGE=[scallop] Error: Required option 'master' not found
_COMM=java
_EXE=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.171-7.b10.el7.x86_64/jre/bin/java
_CMDLINE=java -cp /usr/share/marathon/lib/mesosphere.marathon.marathon-1.6.352.jar:/usr/share/marathon/li
_STREAM_ID=bd3ee42018a94236baeab1e5f653171f
_PID=24962
经过上述日志能够看出,是找不到master致使启动失败。检查了下以上关于marathon的全部配置,确认没有问题。能够根据以下办法直接带master参数启动marathon,最终成功!
# which marathon
/usr/bin/marathon
# nohup marathon --master zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/mesos --zk zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/marathon & >>nohup.out
# ss -tunlp|grep 8080 #8080端口为marathon的进程监听端口
tcp LISTEN 0 50 :::8080 :::* users:(("java",pid=17946,fd=179))
查看application的metric
# curl http://192.168.8.131:8080/metrics | python -m json.tool | less
查看运行的app
# curl http://192.168.8.131:8080/v2/apps | python -m json.tool
查看ID为nginx-test的app
# curl http://192.168.8.131:8080/v2/apps/nginx-test | python -m json.tool
删除ID为nginx-test的app
# curl -X DELETE http://192.168.8.131:8080/v2/apps/nginx-test | python -m json.tool
以slave-node1为例,slave-node2配置根据环境微调。
# yum install mesos docker –y
# vi /etc/mesos/zk
zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/mesos
# echo "docker,mesos" >/etc/mesos-slave/containerizers
# echo "192.168.8.134">/etc/mesos-slave/ip
# echo "192.168.8.134" >/etc/mesos-slave/hostname
# systemctl stop mesos-master
# systemctl disable mesos-master
# systemctl enable mesos-slave docker
# systemctl start mesos-slave docker
# systemctl status docker
报错:Unit dockergetenforce.service could not be found.
解决方法:
重启服务
# systemctl status mesos-slave
登录mesos web:http://192.168.8.131:5050/#/
1. 从首页能够看到mesos-agent:activated状态的agent有2个;
2. mesos-master管理的2个agent的资源已汇总。
1. 在mesos框架中,marathon框架已经被识别,marathon的leader是:mesos-master2;
2. 虽然mesos-master与marathon的leader相同,但二者的leader是zookeeper独立选举的,并无直接关系,是能够不一样的。
1.在Agnets中能看到2个agent;
2.同时能看到每一个agent的资源;
点击上面2个slave中的任意一个,也能看出它的master是mesos-master2
访问marathon的管理页面,http://master_ip:8080
这里的master_ip就是在上面访问mesos页面Frameworks中识别出的marathon,即192.168.8.132:8080
或者直接点击mesos访问页面Frameworks中识别出的marathon也能够。
浏览器访问:http://192.168.8.132:5050/master/state
好比建立一个nginx镜像的Docker容器,Marathon启动时会读取/etc/mesos/zk配置文件,Marathon经过Zookeeper来找到Mesos Master。
1)Marathon有本身的REST API,咱们经过API的方式来建立一个 tomcat 的Docker容器
首先建立一个json文件(这个要在master节点机器上建立,任意一台master节点机上均可以):
# docker pull nginx
# docker pull tomcat
nginx-example:
{
"id":"nginx", #容器名,只在marathon生效
"cpus":0.2, #cpu用量
"mem":32.0, #mem用量
"instances": 1, #容器数量
"constraints": [["hostname", "UNIQUE",""]], #限制
"container": {
"type":"DOCKER", #应用类型
"docker": { #docker具体配置
"image": "docker.io/nginx", #采用的image
"network": "BRIDGE", #网络模式
"portMappings": [
{"containerPort": 80, "hostPort": 0,"servicePort": 0, "protocol": "tcp" }
] #端口映射,”0”表示任意端口,"servicePort"服务端口
}
}
}
# vi tomcat.json # tomcat
的docker镜像要提早建立或下载
{
"id":"tomcat-1",
"cpus":0.5,
"mem":64,
"instances": 1,
"constraints": [["hostname", "CLUSTER",""]],
"container": {
"type":"DOCKER",
"docker": {
"image": "docker.io/tomcat",
"network": "BRIDGE",
"portMappings": [
{"containerPort": 8080, "hostPort": 0,"servicePort": 0, "protocol": "tcp" }
]
}
}
}
注意:json文件中的每一行内容的开头和结尾必定不能有空格,但能够有空行,不然手动经过curl的方式建立容器实例,会有各类各样的报错!!!
接着使用curl的方式调用,注意上面的tomcat.json
文件是在/root路径下的(注意下面命令中json文件路径)。
# curl -X POST http://192.168.8.131:8080/v2/apps -d @/root/tomcat.json -H "Content-type: application/json"
{"id":"/tomcat-1","backoffFactor":1.15,"backoffSeconds":1,"constraints":[["hostname","CLUSTER",""]],"container":{"type":"DOCKER","docker":{"forcePullImage":false,"image":"docker.io/tomcat","parameters":[],"privileged":false},"volumes":[],"portMappings":[{"containerPort":8080,"hostPort":0,"labels":{},"protocol":"tcp","servicePort":0}]},"cpus":0.5,"disk":0,"executor":"","instances":1,"labels":{},"maxLaunchDelaySeconds":3600,"mem":64,"gpus":0,"networks":[{"mode":"container/bridge"}],"requirePorts":false,"upgradeStrategy":{"maximumOverCapacity":1,"minimumHealthCapacity":1},"version":"2018-05-20T09:20:37.589Z","killSelection":"YOUNGEST_FIRST","unreachableStrategy":{"inactiveAfterSeconds":0,"expungeAfterSeconds":0},"tasksStaged":0,"tasksRunning":0,"tasksHealthy":0,"tasksUnhealthy":0,"deployments":[{"id":"8035fe3f-44a7-4c8d-9f8f-22ecf66ea24f"}],"tasks":[]}
也能够将上面的tomcat.json文件内容直接复制到marathon建立应用容器的"JSON Mode"模式里,而后直接点击建立。
登录marathon界面查看是在哪一台slave机器上建立的docker容器实例(这个是随机的),点击"running"。(若是容器建立失败,即非"running"状态,能够尝试重启slave节点的docker服务)
而后登录mesos-slave1机器,发如今服务器上,这个容器只是被关闭了(docker ps -a),能够选择删除。若是再次在机器上启动这个nginx容器,那么在marathon上是不会显示的。
注意:在节点机器上手动建立的docker容器,这些容器信息是不会在marathon和mesos里展现的。
在marathon界面里"Destory"删除对应的application后,在mesos界面的"Active Tasks"里的对应任务也会删除。
另外要注意:在marathon界面里经过调用mesos建立docker容器,只能建立应用容器(Application),如nginx、tomcat、mysql、redis等,须要映射端口,这里是映射的是宿主机的随机端口。不能建立基本centos,ubuntu的系统容器!
2)nginx实例扩容
点击marathon首页正在运行的nginx实例最后面的"…",选择"Scale",在弹出来的实例扩容对话框中,输入所要扩容的实例个数,肯定后进行扩容。很快会看到原来正在运行的nginx单实例由一个变为多个。Marathon的实例扩容同时也有相应的API,也能够在bash下经过api进行扩容。
访问所建立的nginx容器。(marathon ui界面里建立的docker容器映射到宿主机的访问端口默认都是随机分配的(BRIDGE模式))、能够本身制做应用的docker镜像,或者自定义构建容器并提交为新镜像(本身设定应用容器结构),而后根据本身制做的镜像在Marathon上建立应用。
如以上截图中可知,这个nginx容器是在mesos-slave1节点机(192.168.8.134)上建立的
注意:若是mesos-slave1节点机宕机或docker服务重启,那么这个nginx容器就会自动漂移到其余的slave节点机上;另外,经过上面方式建立好的容器,在单个slave节点机上删除后,容器也会自动转移到其余slave节点机器上,这样就实现了在slave节点出现故障时容器自动转移的高可用功能。
能够登录mesos-slave1机器查看所建立的容器,如上可知:访问Docker随机启动的端口是31725。
接着访问mesos页面,能够看到"Active Tasks"有刚才建立的nginx任务了。(注意:只有当mesos访问界面"Active Tasks"里有容器建立任务时,才说明此容器真正建立成功了)
3)图形化建立并运行容器
而后填写建立容器的配置信息,以下图,能够点击"New Application"建立页面右上角的"JSON Mode"模式,将上面建立nginx容器的json文件复制到这里。
剩下以上红框中的配置选项暂时先不配置,待之后测试。
4)删除marathon建立的docker实例。以下图,点击"Destory"便可删除
Marathon还能够对App应用实现手动扩缩的功能,选择"Scale Application"进行快速扩容。以下图,对上面已建立的tomcat应用容器进行扩展到2个Task(注意:这里有2个slave节点,那么扩展的Task实例最好是2个,即2个Instances;若是扩展多个Task,会发现多余的建立失败,这时候能够点击"Configuration"修改,修改为2个)。
点击下面的日志"stderr"和"stdout"就会下载到本地。
也能够到mesos页面查看或下载。点击下面mesos页面对应容器任务后面的"Sandbox"
具体配置能够参考marathon官方文档:https://mesosphere.github.io/marathon/docs/persistent-volumes.html里面有关于json文件的配置
在marathon界面里建立应用,可使用volumes,即映射容器目录到宿主机上,JSON文件内容以下:
{
"id": "nginx-1",
"cmd": null,
"cpus": 0.5,
"mem": 32,
"disk": 2048,
"instances": 1,
"container": {
"docker": {
"image": "docker.io/nginx",
"network": "BRIDGE",
"portMappings": [
{
"containerPort": 80,
"protocol": "tcp",
"name": null,
"labels": null
}
]
},
"type": "DOCKER",
"volumes": [
{
"containerPath": "/usr/share/nginx/html",
"hostPath": "/opt/web/www",
"mode": "RW"
}
]
}
}
# mkdir -p /opt/web/www //如上图在192.168.8.135(mesos-slave2)节点上建立使用的卷目录(volumes,即映射的宿主机目录)
# echo "test" > /opt/web/www/index.html //映射的宿主机目录下建立测试文件
注意事项:
1)映射到宿主机的目录/opt/web/www要在每一个slave节点机器上都要建立,而且里面的文件要在每一个slave节点机上都有,由于容器重启后会在各个slave节点之间随机漂移。 2)上面映射的是nginx容器应用的站点目录,默认建立后,/usr/share/nginx/html是空的(/opt/web/www目录也是空的),因此容器默认访问会出现403报错。只需在slave节点的/opt/web/www目录下编写html文件(如index.html)便可访问。 3)marathon里建立好的容器应用,你能够在对应的slave机器上登录容器内修改,可是这个容器应用一旦在marathon界面里restart,那么你以前的修改就没有了。由于重启应用,就是再次使用初始镜像进行构建了。 4)能够本身制做应用镜像,在镜像里设定好应用的配置文件;或者将本身建立的容器提交为新的镜像。而后在marathon界面里根据本身定义的镜像建立应用。 |
默认状况下,marathon建立的应用访问端口是随机分配的,由于hostPort默认配置的是0,具体看下面说明:
marathon建立应用后,会涉及到三个端口:containerPort:、hostPort、servicePort,其中:
1)containerPort:用来指定容器内部的一个端口。当使用BRIDGE或USER网络模式链接Docker容器时,必须将这个属性设置为port mapping的一部分。
2)hostPort:用来指定绑定到主机上的一个端口。当使用BRIDGE或USER网络模式,你能够指定一个port mapping将一个主机端口映射到容器端口。在HOST网络模式下,默认的请求端口就是主机的端口。
请注意,主机端口只能够经过环境变量提供给一个任务。
3)servicePort:当您在Marathon上(无论是经过REST API或界面)建立一个新的应用程序,你能够指定一个或多个服务端口给它。
能够指定全部有效的端口号为服务端口,也能够用0表示Marathon应该自动分配的可用服务端口给应用程序使用。若是你选择本身的服务端口,你必须本身确保,这个端口在全部应用程序中是惟一的。
portMapping:在Docker BRIDGE模式下,在容器外部可被访问到的端口都须要作端口映射。端口映射是一个包含host port, container port, service port和协议的元组。能够为Marathon应用指定多个端口映射; 未指定hostPort,则其默认值为0(意味着Marathon将随机分配一个)。在Docker USER模式下,hostPort的语义为稍有点变化:USER模式不须要指定hostPort,若是未指定Marathon不会自动分配一个随机的。这容许在USER网络模式下部署容器,包括containerPort和发现信息,但不暴露主机网络上的这些端口(意味着将不消耗主机端口资源)。
marathon建立应用的网络模式介绍:
1)BRIDGE网络模式:指定Docker应用程序使用BRIDGE网络模式。在这种模式下,容器端口(容器内部的端口)被映射到主机端口(宿主机上的端口)。在这种模式下,应用程序被绑定到容器内的指定端口,容器的端口被绑定到宿主机上的指定端口。
2)USER网络模式:指定Docker应用程序使用USER网络模式。在这种模式下,容器端口(容器内部的端口)被映射到主机端口(宿主机上的端口)。在这种模式下,应用程序被绑定到容器内的指定端口,容器的端口被绑定到宿主机上的指定端口。在与“用户自定义”Docker网络集成时,USER网络模式将会很是有用。在Mesos世界,这种网络一般是经过使用与Mesos CNI网络隔离的 CNI 插件访问。
3)HOST网络模式:该种模式在Marathon应用为非容器化而其它应用为容器化的状况下使用。在这种模式下,应用程序直接绑定到宿主机上的一个或多个端口。
以下JSON文件内容,注意一下:若是hostport端口指定了,那么serviceport端口也要指定(最好使用大端口),不然会致使应用容器建立失败。
{
"id":"nginx-2",
"cpus":0.2,
"mem":32.0,
"instances": 1,
"constraints": [["hostname", "CLUSTER",""]],
"container": {
"type":"DOCKER",
"docker": {
"image": "docker.io/nginx",
"network": "BRIDGE",
"portMappings": [
{"containerPort": 80, "hostPort": 31030,"servicePort": 33180, "protocol": "tcp" }
]
}
}
}
在marathon界面里建立应用,将上面的JSON文件内容复制到"JSON Mode"模式下。构建成功后,就会发现该应用容器的访问端口就是上面本身定义的31030端口了(以下)
在marathon中,应用是一个完整的概念。每一个应用是一个典型的长运行的服务,这个服务有不少实例,而且是运行在多个slave节点机上。下面经过一个小示例说明下:
一个内嵌的shell脚步:
以下经过内嵌的shell脚步,编写一个简单的app,即:
打印Hello world到slave节点的/mnt/test文件中,而后sleep 5秒,周而复始。可使用下面的应用定义文件(json格式)来描述应用(注意:cmd是要执行的命令。它的值会以/bin/sh -c ${cmd}的方式执行。):
{ "id": "basic-0", "cmd": "while [ true ] ; do echo 'Hello world' >> /mnt/test ; sleep 5 ; done", "cpus": 0.1, "mem": 10.0, "instances": 1 } |
在marathon界面里添加应用,采用"JSON Mode "模式,以下:
不采用"JSON Mode"模式,即将上面的json文件内容粘贴进去后,去掉右上方的"JSON Mode"模式,也就是只配置"General"选向,其余选项都不配置。注意:marathon里的应用是一个长运行服务,因此shell脚本里要配置长运行动做。
而后到192.168.8.135这台slave节点机上检查,发现每隔5秒钟,就会输出"hello world"到/mnt/test文件中。若是这台节点机出现故障,就会输出到其余节点机上。
# tail -f /mnt/test
Hello world
Hello world
Hello world
Hello world
***************当你发现本身的才华撑不起野心时,就请安静下来学习吧!**************
下图是chronos任务调度系统的基本结构图:
总体上来看,该系统由业务队列、业务调度器、Chronos和Mesos组成。每一个组成部分的说明以下:
业务队列:实际存听任务的队列,队列中的任务能够是按照优先级排序,也能够是FIFO. 多个业务队列表示不一样的业务,或者同一业务的不一样队列。
业务调度器:根据必定的调度算法从多个业务队列中选择任务来调度。业务调度器接受Chronos的资源汇报,而后给这些资源分配任务。
Chronos:向业务调度器汇报剩余资源,接受业务调度器提交的任务而后在Mesos集群上面运行。
Mesos:运行各个Docker容器的载体。每一个任务都在Docker容器中执行。
有一点须要解释的是,在这个任务调度系统中,存在多个调度器:
Mesos中的调度器:一种通用的集群资源分配算法,也就是DRF
Chronos中的调度器:在咱们这个场景中,不须要定时调度任务。咱们只需使用Chronos的Rest API提交一个Docker任务就能够了,这个Docker任务而后由Chronos调度到Mesos集群上面运行。为何不绕过Chronos直接提交任务到Mesos呢?Mesos自己是个两级调度架构,若是绕过Chronos,那么业务调度器就须要实现Mesos的上级调度接口,增长了复杂性。
业务调度器:这就是和业务联系最紧密的地方了,此处必须考虑各类业务特性,好比各个业务队列的任务总量、到达速率、优先级等等。
系统的核心在于业务调度器。通过调研各类调度算法,以为YARN资源管理系统中的容量调度(Capacity Scheduler)适合多业务多队列的场景。
以两级队列为例来讲明容量调度算法。下图是Chronos资源的容量配置示例:
在该示意图中,Chronos资源容量的20%分配给了业务1,80%分配给了业务2. 接着,20%容量中的40%分配给了业务队列11,60%分配给了业务队列12. 业务1和业务2是业务层次的队列,业务队列十一、业务队列12和业务队列21是具体业务下的子队列。
拉取docker官方chronos镜像
# docker pull mesosphere/chronos
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/mesosphere/chronos latest ec8accd8eb53 15 months ago 511 MB
# docker run -itd --net=host -e PORT0=18080 -e PORT1=8081 docker.io/mesosphere/chronos:latest --zk_hosts zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181 --master zk://192.168.8.131:2181,192.168.8.132:2181,192.168.8.133:2181/mesos
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a6f9ecd25d38 docker.io/mesosphere/chronos:latest "/chronos/bin/star..." 2 minutes ago Up 2 minutes gallant_wescoff
注意:时间是UTC时间
Name: 做业名称
Command: 实际须要执行的命令
Schedule: 做业的调度规则,遵循ISO8601规范。由三部分组成,经过”/“符号分割。例如”R10/2012-10-01T05:52:00Z/PT2S”的三部份内容以下:
1> 重复执行做业务次数,若是只有一个R,则表明无限次执行。
2> 开始启动做业的时间,若是为空,则表示当即执行,其遵循ISO8601规范。
3> 执行频率(即间隔多长时间执行一次),其定义方式以下:
P10M=10 months
PT10M=10 minutes
P1Y12M12D=1 years plus 12 months plus 12 days
P12DT12M=12 days plus 12 minutes
P1Y2M3DT4H5M6S=P(eriod) 1Y(ear) 2M(onth) 3D(ay) T(ime) 4H(our) 5M(inute) 6S(econd)
其中,P是必选字段,T是可选字段,用来区分M(inute)和M(onth)。
ScheduleTimeZone: 用来设置做业调度的时区。
Epsilon: 指因某些缘由Chronos丢失了运行做业的下一次时间时,采用的固定运行周期。
Owner: 做业责任人的邮件地址。
Async: 做业是否在后台运行。
chronos任务若是正常调度并执行的话,在mesos的web页面上的“Active Tasks”下会有任务执行相关的信息,以下图:
也能够在Chronos的任务页面,点击「Run」强制执行。
启动Docker,抓取nginx镜像,启动chronos-nginx容器
A、建立json文件
# vi chronos-test.json
{
"container": {
"type": "DOCKER",
"image": "docker.io/nginx",
"network": "HOST"
},
"schedule": "R/2018-05-30T14:00:00.000Z/PT24H",
"name": "chronos-nginx",
"cpus": "0.3",
"mem": "32",
"uris": [],
"command": "/usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf"
}
network": "BRIDGE",由于Docker默认的网络模式是桥接,不指定默认也是BRIDGE,此处指定为“HOST”。
B、经过BASH调用chronos的RestfulAPI调度接口运行并启动chronos-nginx容器
# curl -L -H 'Content-Type: application/json' -X POST -d @/root/chronos-test.json http://192.168.8.131:18080/v1/scheduler/iso8601
在chronos的web管理界面上查看chronos-nginx容器运行的状态以下图:
在Mesos页面确认任务的详细信息,以下图:
在节点上确认容器启动,以下图:
# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
db3165da2284 docker.io/nginx "/bin/sh -c '/usr/..." 9 minutes ago Up 9 minutes 80/tcp mesos-97cce9bb-a884-454e-aed7-dea10d68737e
consul的架构图以下所示:
启动consul后默认会监听5个端口:
8300: replication、leader farwarding的端口
8301: lan gossip的端口
8302: wan gossip的端口
8500: web ui界面的端口
8600: 使用dns协议查看节点信息的端口
集群角色:
上图是官方的consul cluster的架构,Consul Cluster有Server和Client两种角色。无论是Server仍是Client,统称为Agent,Consul Client是相对无状态的,只负责转发RPC到Server,资源开销不多。Server是一个有一组扩展功能的代理,这些功能包括参与Raft选举,维护集群状态,响应RPC查询,与其余数据中心交互WAN gossip和转发查询给leader或者远程数据中心。
在每一个数据中心,client和server是混合的。通常建议有3-5台server。这是基于有故障状况下的可用性和性能之间的权衡结果,由于越多的机器加入达成共识越慢,Server之间会选举出一个leader。然而,并不限制client的数量,它们能够很容易的扩展到数千或者数万台。
consul更像一个“全栈”解决方案,内置了服务注册与发现,具备健康检查、Key/Value存储、多数据中心的功能。我的比较偏心他有三点:
一、开箱即用,方便运维:安装包仅包含一个可执行文件,方便部署,无需其余依赖,与Docker等轻量级容器可无缝配合;
二、自带ui界面,能够经过web界面直接看到注册的服务,更新K/V;
三、采用GOSSIP协议进行集群内成员的管理和消息的传播,使用和etcd同样的raft协议保证数据的一致性。
Consul提供的四个关键特性:
一、服务发现:提供HTTP和DNS两种发现方式。
二、健康监测: 支持多种方式,HTTP、TCP、Docker、Shell脚本定制化监控。
三、K/V存储: Key、Value的存储方式。
四、多数据中心:Consul支持多数据中心。
固然Consul还有不少锦上添花的特性,好比:可视化Web界面、配置模板“consul-template”等。
经过registrator的服务自动注册,配合consul服务,在docker容器中可以自动识别服务的域名,以便在mesos+marathon中部署docker实例可以经过域名互通,也就是consul在docker容器中的自动发现。若是是线上consul server最少3台作集群,consul client是每一个mesos-slave上跑一个,mesos-master也最少3台集群,marathon和zookeeper都应该是集群的模式。
consul常常拿来和etcd、zookeeper来对比,他有和etcd同样的服务发现、服务注册功能,也有和etcd、zookeeper同样的配置存储功能,详细的比对这里就不描述了。下面是consul集群的服务注册,服务发现,健康检查,和模板使用。
registrator服务注册 | | consul服务端 | |nginx代理 | |应用服务
作健康检查 | |接收客户端发送的健康 | | 若是nginx的模板 | |
肯定本地服务是否正常 | |检查信息作服务的注册 | |更改,则 | |
通报给consul服务端 | |若是客户端有变更,则 | |nginx reload | |
| |更新代理的配置 | | | |
# unzip consul_1.1.0_linux_amd64.zip -d /usr/local
# ln -s /usr/local/consul /usr/local/bin/consul
# mkdir -p /etc/consul.d //在每一个consul节点上配置
command方式建立consul集群:
# consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=192.168.8.131 -config-dir=/etc/consul.d -client 0.0.0.0
==> Multiple private IPv4 addresses found. Please configure one with 'bind' and/or 'advertise'.
报错:Multiple private IPv4 addresses found. Please configure one with 'bind' and/or 'advertise'.
意思是:找到多个私有IPv4地址。请用“bind”绑定配置一个,就能够解决,根据提示.
[root@mesos-master1 ~]# nohup consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=mesos-master1 -config-dir=/etc/consul.d -bind=192.168.8.131 -client 0.0.0.0 -ui &
bootstrap_expect > 0: expecting 3 servers
==> Starting Consul agent...
==> Consul agent running!
Version: 'v1.1.0'
Node ID: 'cc8eebd0-6f84-6eee-f8cc-92ae7bf44494'
Node name: 'mesos-master1'
。。。。。。
2018/06/03 15:00:21 [INFO] agent: Started DNS server 0.0.0.0:8600 (tcp)
2018/06/03 15:00:21 [INFO] agent: Started HTTP server on [::]:8500 (tcp)
2018/06/03 15:00:21 [INFO] agent: started state syncer
2018/06/03 15:00:28 [ERR] agent: failed to sync remote state: No cluster leader
2018/06/03 15:00:30 [WARN] raft: no known peers, aborting election
2018/06/03 15:00:51 [ERR] agent: Coordinate update error: No cluster leader
2018/06/03 15:00:54 [ERR] agent: failed to sync remote state: No cluster leader
报错:No cluster leader,是由于其它两台consul的server端尚未启动!
启动参数说明:
agent: 运行一个consul代理。
-server: 切换代理到服务器模式。
-bootstrap: 当consulserver-node1节点启动以后,等待另外两个节点的加入,3个节点聚齐后,以后才开始选举leader。
-ui: 启用内置的静态web UI服务器。
-data-dir: 路径到数据目录存储代理状态。
-bind: 设置集群通讯的绑定地址。
-client: 设置用于绑定客户端访问的地址。这包括RPC、DNS、HTTP和HTTPS(若是配置)。
-node: 此节点的名称。 在集群中必须是惟一的,若是你运行第2台consul,能够写server0二、server03等。
-advertise:若是要让节点在WAN网络中被发现,就要配置这个参数,暴露出外网ip
[root@mesos-master2 ~]# nohup consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=mesos-master2 -config-dir=/etc/consul.d -bind=192.168.8.132 -client 0.0.0.0 -join 192.168.8.131 & //注意:此处的-join启动选项,后面跟mesos-master1的IP地址,或者也能够在mesos-master1上执行consul join 192.168.8.132/133,不然一样仍是会报以上错误!
[root@mesos-master3 ~]# nohup consul agent -server -bootstrap-expect=3 -data-dir=/tmp/consul -node=mesos-master3 -config-dir=/etc/consul.d -bind=192.168.8.133 -client 0.0.0.0 -join 192.168.8.131 &
很×××台mesos-master上的consul都会打印:
consul: New leader elected: mesos-master1
证实此时leader已经选出,集群能够正常工做。
[root@mesos-slave1 ~]# nohup consul agent -client 192.168.8.134 -data-dir=/tmp/consul -config-dir=/etc/consul.d -node=mesos-slave1 -bind=192.168.8.134 -join 192.168.8.131 &
[root@mesos-slave2 ~]# nohup consul agent -client 192.168.8.135 -data-dir=/tmp/consul -config-dir=/etc/consul.d -node=mesos-slave2 -bind=192.168.8.135 -join 192.168.8.131 &
[root@mesos-master1 ~]# consul info consul
集群参数put/get测试:
[root@mesos-slave1 ~]# consul kv put key value
Success! Data written to: key
[root@mesos-master2 ~]# consul kv get key
value
5台机器获取key的值均为value,如此可知key的值已经在集群中同步。
[root@mesos-master1 ~]# consul members
Node Address Status Type Build Protocol DC Segment
mesos-master1 192.168.8.131:8301 alive server 1.1.0 2 dc <all>
mesos-master2 192.168.8.132:8301 alive server 1.1.0 2 dc <all>
mesos-master3 192.168.8.133:8301 alive server 1.1.0 2 dc <all>
mesos-slave1 192.168.8.134:8301 alive client 1.1.0 2 dc <default>
mesos-slave2 192.168.8.135:8301 alive client 1.1.0 2 dc <default>
[root@mesos-master1 ~]# consul operator raft list-peers
Node ID Address State Voter RaftProtocol
mesos-master1 f0522384-3554-61e7-57ce-607a583a179f 192.168.8.131:8300 leader true 3
mesos-master2 b5ffff40-f993-0f9e-7877-4e0bffdabb3d 192.168.8.132:8300 follower true 3
mesos-master3 fc42ff3f-617f-9524-090b-b8c5584b3cac 192.168.8.133:8300 follower true 3
能够看出集群中mesos-master1是leader,mesos-master2和mesos-master3都是follower
[root@mesos-master1 ~]# consul info |grep leader
leader = false
leader_addr = 192.168.8.132:8300
[root@mesos-master1 ~]# consul catalog services
consul
mesos
配置文件方式建立consul集群:
在其中一个mesos master节点上配置bootstrap配置,该节点就是consul集群中的bootstrap节点(192.168.8.131)。
# cat > /etc/consul.d/bootstrap/config.json <<EOF
{
"bootstrap": true,
"server": true,
"datacenter": "dc",
"data_dir": "/var/consul",
"log_level": "INFO",
"enable_syslog": true,
"disable_update_check": true,
"ui": true
}
EOF
在其余的mesos master 节点上配置server配置,这些节点就是consul集群中的server节点(192.168.8.132/192.168.8.133)。
# cat > /etc/consul.d/server/config.json <<EOF
{
"bootstrap": false,
"server": true,
"datacenter": "dc",
"data_dir": "/var/consul",
"log_level": "INFO",
"enable_syslog": true,
"disable_update_check": true,
"start_join": ["192.168.8.131", "192.168.8.133"],
"ui": true
}
EOF
注意: start_join: 记录了其余consul server节点的IP。
在全部的mesos agent 节点上配置client配置,这些节点也就是consul集群中的client节点
# cat > /etc/consul.d/client/config.json <<EOF
{
"server": false,
"datacenter": "dc",
"data_dir": "/var/consul",
"log_level": "INFO",
"enable_syslog": true,
"disable_update_check": true,
"start_join": ["192.168.8.131", "192.168.8.132", "192.168.8.133"],
"ui": true
}
EOF
注意:start_join: 记录了全部的consul server的IP。
启动Consul集群:
在consul bootstrap节点启动:
# consul agent -config-dir /etc/consul.d/bootstrap/ -bind=192.168.8.131 -client=0.0.0.0 >> /var/log/consul.log 2>&1 &
在全部consul server节点启动:
# consul agent -config-dir /etc/consul.d/server/ -bind=192.168.8.132 -client=0.0.0.0 >> /var/log/consul.log 2>&1 &
在全部consul client节点启动:
consul agent -config-dir /etc/consul.d/client/ -bind=192.168.8.134 -client=0.0.0.0 >> /var/log/consul.log 2>&1 &
注意: self_ip是本机的IP。
检查consul集群状态:
在consul集群中任意一个节点执行
consul支持dns的服务注册:
# dig @127.0.0.1 8600 mesos-master1.node.consul +short
192.168.8.131
# dig @127.0.0.1 8600 mesos-master2.node.consul +short
192.168.8.132
# dig @127.0.0.1 8600 mesos-master3.node.consul +short
192.168.8.133
对consul来讲一个重要的接口就是RESTful HTTP API,http api可用于操做nodes, services, checks, configuration等等的CRUD(create, read, update and delete),详见Consul Http Api,下面是几个例子?说明
http api能够经过连接请求:
查看当前consul节点的服务
# curl mesos-master1:8500/v1/agent/checks |python -m json.tool
查看当前consul集群的leader
# curl mesos-master1:8500/v1/status/leader
查看当前节点的信息
# curl mesos-master1:8500/v1/operator/raft/configuration |python -m json.tool
查看mesos-slave1节点的健康检查信息
# curl mesos-master1:8500/v1/health/node/mesos-slave1 |python -m json.tool
查看webserver服务的信息
# curl -s http://mesos-master1:8500/v1/catalog/service/webserver | python -m json.tool
# 集群server成员
#curl 127.0.0.1:8500/v1/status/peers
# 集群Raft leader
#curl 127.0.0.1:8500/v1/status/leader
# 注册的全部服务
#curl 127.0.0.1:8500/v1/catalog/services
# 服务信息
#curl 127.0.0.1:8500/v1/catalog/services/nginx
# 集群节点详细信息
#curl 127.0.0.1:8500/v1/catalog/nodes
服务发现与注册
1. 具体流程
服务注册中心:做为整个架构中的核心,要支持分布式、持久化存储,注册信息变更实时通知消费者。
服务提供者:服务以容器化方式部署(实现服务端口的动态生成),能够经过 的方式来管理。经过 检测到 进程信息以完成服务的自动注册。
服务消费者:要使用服务提供者提供的服务,和服务提供者每每是动态相互转位置的。
一个较为完整的服务注册与发现流程以下:
注册服务:服务提供者到注册中心注册;
订阅服务:服务消费者到注册中心订阅服务信息,对其进行监听;
缓存服务列表:本地缓存服务列表,减小与注册中心的网络通讯;
调用服务:先查找本地缓存,找不到再去注册中心拉取服务地址,而后发送服务请求;
变动通知:服务节点变更时 (新增、删除等),注册中心将通知监听节点,更新服务信息。
2. 相关组件
一个服务发现系统主要由三部分组成:
注册器(registrator):根据服务运行状态,注册/注销服务。主要要解决的问题是,什么时候发起注册/注销动做。
注册表(registry):存储服务信息。常见的解决方案有zookeeper、etcd、cousul等。
发现机制(discovery):从注册表读取服务信息,给用户封装访问接口。
经过Registrator收集须要注册到Consul做为Nginx后端服务器信息而后注册到Consul key/value.Consul-template去Consul key/value中读取信息,而后自动修改Nginx配置文件并平滑重启Nginx,不须要修改nginx.conf。
分别在mesos-slave1 和mesos-slave2 上都建立:
利用chronos的任务调度下载registrator:
利用chronos的任务调度在全部的mesos-slave上运行registrator:
Command: docker run -d --name registrator --network=host -v /var/run/docker.sock:/tmp/docker.sock --restart=always gliderlabs/registrator:latest --ip 192.168.8.134 consul://192.168.8.131:8500
参数说明:
--network:把运行的docker容器设定为host网络模式;
-v /var/run/docker.sock:把宿主机的Docker守护进程(Docker daemon)默认监听的Unix域套接字挂载到容器中;
--ip : 刚才把network指定了host模式,因此咱们指定下IP为宿主机的IP;
consul: 最后这个选项是配置consul服务器的IP和端口。
服务注册前:
经过marathon启动tomcat服务:
[root@mesos-master1 ~]# curl -X POST http://192.168.8.131:8080/v2/apps -d @/root/tomcat.json -H "Content-type: application/json"
{"id":"/tomcat-1","backoffFactor":1.15,"backoffSeconds":1,"constraints":[["hostname","CLUSTER",""]],"container":{"type":"DOCKER","docker":{"forcePullImage":false,"image":"docker.io/tomcat","parameters":[],"privileged":false},"volumes":[],"portMappings":[{"containerPort":8080,"hostPort":0,"labels":{},"protocol":"tcp","servicePort":0}]},"cpus":0.5,"disk":0,"executor":"","instances":1,"labels":{},"maxLaunchDelaySeconds":3600,"mem":64,"gpus":0,"networks":[{"mode":"container/bridge"}],"requirePorts":false,"upgradeStrategy":{"maximumOverCapacity":1,"minimumHealthCapacity":1},"version":"2018-06-10T08:34:47.600Z","killSelection":"YOUNGEST_FIRST","unreachableStrategy":{"inactiveAfterSeconds":0,"expungeAfterSeconds":0},"tasksStaged":0,"tasksRunning":0,"tasksHealthy":0,"tasksUnhealthy":0,"deployments":[{"id":"346444ac-978b-42d6-8975-6b01fd6869ab"}],"tasks":[]}
服务注册后:
从上图能够看出,刚才建立的marathon应用tomcat容器服务已经注册到了 consul中。
[root@mesos-master1 ~]# curl 127.0.0.1:8500/v1/catalog/services
{"consul":[],"mesos":["master","leader"],"tomcat":[]}
服务被调整后,负载均衡要想动态从新分配负载,就须要修改相应的配置文件,consul-template就是解决这个问题的应用,经过监听consul的注册信息,来自动完成负载均衡相应的配置更新。
安装nginx,此处略过。。。
安装consul-template很是简单,下载二进制包便可使用。
1、下载consul-template
下载地址:https://releases.hashicorp.com/consul-template/0.19.4/consul-template_0.19.4_linux_amd64.zip
# wget https://releases.hashicorp.com/consul-template/0.19.4/consul-template_0.19.4_linux_amd64.zip
2、解压并安装到/usr/bin目录
# unzip consul-template_0.19.4_linux_amd64.zip
# mv consul-template /usr/bin/
# consul-template -v
consul-template v0.19.4 (68b1da2)
3、建立nginx模板
# cd /usr/local/nginx
# mkdir consul
# cd consul/
# vi nginx.ctmpl
upstream http_backend {
{{range service "nginx"}}
server {{ .Address }}:{{ .Port }} max_fails=3 fail_timeout=90;
{{ end }}
}
server {
listen 8085;
server_name localhost;
location / {
proxy_pass http://http_backend;
}
}
4、修改nginx.conf
# grep "consul" nginx.conf
include /usr/local/nginx/consul/*.conf; //添加这一行在http模块
# /usr/local/nginx/sbin/nginx //启动nginx服务
5、启动consul-template
# ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx
# cd /usr/local/nginx/consul/
# consul-template --consul-addr 192.168.8.131:8500 --template /usr/local/nginx/consul/nginx.ctmpl:/usr/local/nginx/consul/vhost.conf:"nginx -s reload" --log-level=info
2018/06/18 13:15:45.719503 [INFO] consul-template v0.19.4 (68b1da2)
2018/06/18 13:15:45.720675 [INFO] (runner) creating new runner (dry: false, once: false)
2018/06/18 13:15:45.721967 [INFO] (runner) creating watcher
2018/06/18 13:15:45.723542 [INFO] (runner) starting
2018/06/18 13:15:45.724051 [INFO] (runner) initiating run
2018/06/18 13:15:45.728395 [INFO] (runner) initiating run
2018/06/18 13:15:45.731084 [INFO] (runner) rendered "/usr/local/nginx/consul/nginx.ctmpl" => "/usr/local/nginx/consul/vhost.conf"
2018/06/18 13:15:45.732215 [INFO] (runner) executing command "nginx -s reload" from "/usr/local/nginx/consul/nginx.ctmpl" => "/usr/local/nginx/consul/vhost.conf"
2018/06/18 13:15:45.733669 [INFO] (child) spawning: nginx -s reload
--consul-addr:指定consul服务的ip和端口; ./nginx.ctmpl:这是用nginx.ctmpl这个模板来启动进程,这是写的相对路径,也能够写绝对路径; vhost.conf:nginx.ctmpl模板生成后的文件名,这也能够写绝对路径,若是不写绝对路径,这个文件就在当前目录生成(/usr/local/nginx/consul/)
因为consul-template在前台运行,因此咱们在打开一个终端验证。
[root@mesos-master1 ~]# ps -ef | grep consul-template
root 41543 16705 0 19:33 pts/2 00:00:00 consul-template --consul-addr 192.168.8.131:8500 --template ./nginx.ctmpl:vhost.conf --log-level=info
root 41758 38089 0 19:35 pts/1 00:00:00 grep --color=auto consul-template
[root@mesos-master1 ~]# ll /usr/local/nginx/consul/
total 8
-rw-r--r-- 1 root root 333 Jun 10 18:26 nginx.ctmpl
-rw-r--r-- 1 root root 255 Jun 10 19:33 vhost.conf
在consul目录下,是否是发现多了一个文件vhost.conf,就是刚才启consul-template时生成的。查看下vhost.conf的内容,目前upstraem的server配置为空,尚未docker主机加入进来:
[root@mesos-master1 ~]# cat /usr/local/nginx/consul/vhost.conf
upstream http_backend {
server {{ .Address }}:{{ .Port }} max_fails=3 fail_timeout=90;
}
server {
listen 8085;
server_name localhost;
location / {
proxy_pass http://http_backend;
}
}
经过marathon建立nginx容器实例:
[root@mesos-master1 ~]# curl -X POST http://192.168.8.132:8080/v2/apps -d @/root/nginx.json -H "Content-type: application/json"
{"id":"/nginx-1","backoffFactor":1.15,"backoffSeconds":1,"container":{"type":"DOCKER","docker":{"forcePullImage":false,"image":"docker.io/nginx","parameters":[],"privileged":false},"volumes":[{"containerPath":"/usr/share/nginx/html","hostPath":"/opt/web/www","mode":"RW"}],"portMappings":[{"containerPort":80,"hostPort":0,"labels":{},"protocol":"tcp","servicePort":0}]},"cpus":0.5,"disk":2048,"executor":"","instances":1,"labels":{},"maxLaunchDelaySeconds":3600,"mem":32,"gpus":0,"networks":[{"mode":"container/bridge"}],"requirePorts":false,"upgradeStrategy":{"maximumOverCapacity":1,"minimumHealthCapacity":1},"version":"2018-06-18T13:12:27.037Z","killSelection":"YOUNGEST_FIRST","unreachableStrategy":{"inactiveAfterSeconds":0,"expungeAfterSeconds":0},"tasksStaged":0,"tasksRunning":0,"tasksHealthy":0,"tasksUnhealthy":0,"deployments":[{"id":"0b2969ac-a65d-4ff9-b7b9-f2c5cc29312f"}],"tasks":[]}
[root@mesos-master1 ~]# cat /usr/local/nginx/consul/vhost.conf
upstream http_backend {
server 192.168.8.134:31581 max_fails=3 fail_timeout=90;
server 192.168.8.134:31818 max_fails=3 fail_timeout=90;
server 192.168.8.135:31814 max_fails=3 fail_timeout=90;
}
server {
listen 8085;
server_name localhost;
location / {
proxy_pass http://http_backend;
}
}
[root@mesos-slave1 ~]# echo "mesos-slave1" >/opt/web/www/index.html
[root@mesos-slave2 ~]# echo "mesos-slave2" >/opt/web/www/index.html
能够看到,在经过marathon建立了3个nginx的容器实例后,nginx的虚拟主机配置文件已经被consul-template动态修改。而后访问一下nginx服务器的IP地址,http://192.168.8.131:8085,从下图能够看出是能够访问的:
能够看到nginx的8085负载均衡是能够正常轮询的!!!