天天看点

基于资源编排在专有网络环境下快速部署高可用的Dubbox服务(ZooKeeper版)

本文将介绍在专有网络vpc(virtual private cloud)下,基于资源编排服务,快速部署高可用的dubbox服务的过程。dubbox服务采用的注册中心是zookeeper集群。做这件事情的意义在于:节约部署dubbox的时间,降低部署dubbox过程中出错的风险。

ros 阿里云资源编排(resource orchestration)是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、配置等,并自动完成所有资源的创建和配置,以达到自动化部署、运维等目的。编排模板同时也是一种标准化的资源和应用交付方式,并且可以随时编辑修改,使基础设施即代码(infrastructure as code)成为可能。 ansible ansible是一个简单的自动化it工具。引用ansible官网的介绍就是:“deploy apps.manage systems.crush complexity.ansible helps you build a strong foundation for devops.”。 dubbox zookeeper

本文将从以下三个方面展开介绍:

准备ansible主机

vpc网络环境下快速部署高可用的dubbox服务

总结

本章将从以下两个方面展开:

安装ansible

安装ros sdk

首先需要新建一个vpc,并在这个vpc下创建一个vswitch,在这个vpc和vswitch下申请一台ecs实例,并给这台机器绑定公网ip,方便访问外网。本文所采用的ansible主机(ecs)系统版本信息如下:

这个版本的ecs已经安装了python 2.7.5。

创建好ansible主机以后,我们需要给这台主机安装ansible和ros sdk。ansible用来实现对远程主机的控制,ros sdk用来实现对资源栈的操作。

dubbox服务的快速部署需要借助ansible来完成,本文采用了yum来安装ansible:

ansible默认安装目录为<code>/etc/ansible</code>,安装好以后,<code>/etc/ansible/</code>目录结构如下:

注意:如果采用的是ubuntu系统,安装ansible过程如下:

ros提供了restful api和sdk,本文将介绍用python的方式来调用ros api创建资源。

在调用ros api之前需要安装相关的依赖。

使用pip安装aliyun-python-sdk-core:

使用pip安装ros sdk:

如果ansible主机未安装pip,可使用以下命令安装pip:

本章将从以下五个方面展开:

创建资源栈

编辑inventory文件

构建playbook

执行playbook

部署dubbox服务

创建资源栈的过程主要分为以下三步:

定义ros资源模板

调用ros api,创建资源栈

获取资源栈输出信息

本文通过调用ros api的方式来创建资源栈。

ros资源模板包括以下几种资源类型:

<a href="https://ros.console.aliyun.com/#/resourcetype/detail/aliyun::ecs::instancegroup/metadata">"type": "aliyun::ecs::instancegroup"</a>

在资源模板中使用两组该类型的资源,一组用来定义dubbox控制台集群服务器,一组用来定义zookeeper集群服务器。

<a href="https://ros.console.aliyun.com/#/resourcetype/detail/aliyun::slb::loadbalancer/metadata">"type": "aliyun::slb::loadbalancer"</a>

创建一台slb。

<a href="https://ros.console.aliyun.com/#/resourcetype/detail/aliyun::slb::backendserverattachment/metadata">"type": "aliyun::slb::backendserverattachment"</a>

给slb添加后端服务器。

<a href="https://ros.console.aliyun.com/#/resourcetype/detail/aliyun::slb::listener/metadata">"type": "aliyun::slb::listener"</a>

配置slb监听,slb监听dubbox控制台集群服务器的8080端口,并配置了健康检查<code>healthcheck</code>。

资源栈的输出为<code>"outputs"</code>,包括:ecsprivateips(dubbox控制台集群服务器的私有ip),zkprivateips(zookeeper集群服务器的私有ip),loadbalanceip(负载均衡slb的公网ip)。

在vpc网络环境下,给instancegroup指定vpc和vswtich,并保证和anisble主机处在同一个vpc和vswitch下,这样才能保证ansible主机可通过ecs的私有ip来登录ecs并操控ecs实例。

定义ros资源模板的python文件为<code>generate_vpc_ros_template.py</code>,文件内容如下:

创建资源栈的python文件为<code>create_stack.py</code>,文件内容如下:

下面详细解释该python文件的执行过程:

初始化sdk客户端对象:

client = acsclient(ak_id, ak_secret, region_id)

初始化创建资源栈的请求:

req = createstacksrequest.createstacksrequest()

指定请求资源region:

req.set_headers({'x-acs-region-id': region_id})

构造请求体,包括:栈名、过期时间戳、ros资源模板

create_stack_body = '''

req.set_content(create_stack_body)

发送请求,创建资源栈:

response = client.get_response(req)

6. 获取资源栈信息:

资源栈创建好以后,我们再次调用ros api获取资源栈的输出信息。方法如下:

调用时需要传入创建好的资源栈<code>id</code>和<code>name</code>信息。由于创建资源栈需要的时间不确定,所以以上方法定义了超时重试的机制。每次重试以后的等待时间要比上次等待时间少<code>interval</code>秒,在尝试<code>attempt</code>次若仍未获取到资源栈信息视为资源创建失败(一般不会出现这种情况)。

资源栈的输出格式如下:

我们将以上输出定义为<code>outputs</code>。

根据上面获取的资源栈输出信息<code>outputs</code>,获取dubbox控制台服务器组的私有ip。方法如下:

根据上面获取的资源栈输出信息<code>outputs</code>,获取zookeeper集群服务器组的私有ip。方法如下:

因为在创建资源栈的时候,已经在配置文件中配置好了<code>aliyun::ecs::instancegroup</code>的登录密码,所以可以直接使用配置文件中的密码信息,用户名默认为root。编辑<code>/etc/ansible/hosts</code>文件,即通常我们所说的<code>ansible inventory</code>文件。编辑该文件的方法如下:

执行该方法以后,生成的<code>inventory</code>文件,即<code>/etc/ansible/hosts</code>文件,内容如下:

<code>inventory</code>文件中定义了两个远程主机组,<code>dubbo_admin</code>和<code>zookeeper</code>,并指定了不同主机的ip、登录协议(默认是 ssh )、登录端口、登录用户名和密码。ansible在执行playbook的时候通过以上信息连接远程主机。

本文所描述的高可用dubbox服务,注册中心采用的是zookeeper集群,因此需要构建两个playbook。一个用来部署dubbox控制台集群,一个用来部署zookeeper集群。

部署dubbox控制台集群的playbook为<code>vpc_dubbox_admin_playbook</code>,结构如下:

关于<code>vpc_dubbox_admin_playbook</code>结构的说明如下:

files

存放<code>install_jdk.sh</code>、<code>install_jetty.sh</code>、<code>deploy_admin.sh</code>三个文件,这三个文件分别用来安装jdk、jetty以及部署dubbox控制台服务。

tasks

存放要执行的yml文件 <code>install_dubbo_admin.yml</code>,文件内容如下:

name: add config

template:

name: run install jdk

script: install_jdk.sh

name: run install jetty

script: install_jetty.sh

name: run deploy admin

script: deploy_admin.sh

templates

存放配置文件模板config.j2,文件内容如下:

配置文件config.j2中的参数值从<code>vpc_dubbox_zk.yml</code>文件中获取,通过ansible执行playbook的过程中会在每一台远程主机的<code>/root</code>目录下生成<code>config</code>文件,提供给<code>install_jdk.sh</code>、<code>install_jetty.sh</code>、<code>deploy_admin.sh</code>这三个脚本使用。关于<code>vpc_dubbox_zk.yml</code>文件,后面会提到。

部署zookeeper集群的playbook为<code>vpc_dubbox_zookeeper_playbook</code>,结构如下:

关于<code>vpc_dubbox_zookeeper_playbook</code>结构的说明如下:

存放<code>install_jdk.sh</code>、<code>install_zk.sh</code>两个文件,这两个文件分别用来安装jdk、部署zookeeper集群。

存放要执行的yml文件 <code>install_zk.yml</code>,文件内容如下:

name: run install zookeeper

script: install_zk.sh

配置文件config.j2中的参数值从<code>vpc_dubbox_zk.yml</code>文件中获取,通过ansible执行playbook的过程中会在每一台远程主机的<code>/root</code>目录下生成<code>config</code>文件,提供给<code>install_jdk.sh</code>、<code>install_zk.sh</code>使用。关于<code>vpc_dubbox_zk.yml</code>文件,后面会说明。

执行playbook,需要以下三个步骤:

生成ansible可执行文件

下载playbook

我们需要通过ansible执行<code>vpc_dubbox_zk.yml</code>文件来运行我们构建好的两个playbook。

<code>vpc_dubbox_zk.yml</code>文件的生成,需要分两步进行:

定义文件模板

生成文件

定义<code>vpc_dubbox_zk.yml</code>文件模板的python文件为<code>deploy_vpc_dubbox.py</code>,文件内容如下:

生成<code>vpc_dubbox_zk.yml</code>文件,方法如下:

生成的<code>vpc_dubbox_zk.yml</code>文件的内容如下:

<code>vpc_dubbox_zk.yml</code>文件中定义了一些参数,下面详细介绍文件中参数的作用:

hosts

远程主机组名称,和<code>inventory</code>文件中的远程主机组相对应。此文件说明要连接的主机组有两个。

vars

配置文件<code>config</code>中的参数,提供给<code>install_jdk.sh</code>、<code>install_jetty.sh</code>、 <code>deploy_admin.sh</code>、<code>install_zk.sh</code>使用。

roles

指定要执行的playbook名称。此文件说明要执行的playbook有两个。

最终生成的<code>vpc_dubbox_zk.yml</code>文件在目录<code>/etc/ansible/</code>下。

ansible是通过ssh命令连接远程主机,并执行playbook的。首次执行playbook前,由于当前ansible主机并没有记录远端主机的rsa key,会弹出rsa key的确认对话框,对话框内容如下:

因为整个过程不用人为的参与,所以可通过python脚本自动实现上述确认的过程:

由于用到了pexpect这个模块,在执行脚本前,需要使用pip安装pexpect模块:

vpc网络环境下未给ecs分配公网ip,导致每台ecs无法下载安装包,但是在安装jdk、jetty以及部署dubbox admin和zookeeper集群的时候需要这些安装包。因为ansible主机配有公网ip,所以可以将安装包先下载到ansible主机,又因为ansible主机和每台ecs在同一个vswitch下面,可以通过scp命令将安装包从ansible主机传到每台ecs上。具体操作过程如下:

在python文件中填入安装包的下载地址,运行python脚本,下载安装包至ansible主机。方法如下:

def wget_files():

通过scp命令将安装包拷贝到每台ecs。方法如下:

def scp_files_from_ansible_host_to_ecs_zk(host_ips, zk_ips):

通过ansible,执行playbook。方法如下:

subprocess.call('ansible-playbook ' + pb_file_dir + '/' + pb_file_name, shell=true)

运行ansible以后会进行dubbox服务的部署过程。

dubbox服务的部署,需要以下两个步骤:

搭建zookeeper集群

搭建dubbox控制台集群

zookeeper集群主要用来作为dubbox服务的注册中心。

搭建zookeeper集群,需要以下两个步骤:

安装jdk

因为zookeeper的运行需要java环境,所以需要先安装jdk。安装jdk的脚本为<code>install_jdk.sh</code>,文件内容如下:

安装jdk过程中,首先需要检查当前ecs是否存在java环境,存在就跳过安装过程,反之则安装。

声明:jdk安装包请从oracle官网下载,并下载本文指定的jdk版本(jdk-8u101-linux-x64.rpm)。从本文链接中下载jdk带来的任何法律问题,和本文作者无关。

搭建zookeeper集群的脚本为<code>install_zk.sh</code>,内容如下:

这个脚本的主要功能是安装zookeeper,并通过修改zookeeper配置文件<code>conf/zoo.cfg</code>来配置zookeeper集群。修改后的配置文件内容如下:

上述文件,配置了三台机器的zookeeper集群。在datadir目录下,创建一个myid文件,里面内容为一个数字,用来标识当前主机号。

由于dubbox控制台需要运行在jetty容器上,jetty容器的运行又需要有java环境,因此部署dubbox控制台之前,需要先安装jdk和jetty。

搭建dubbox控制台集群,需要以下三个步骤:

安装jetty

部署dubbox控制台

安装jetty的文件为<code>install_jetty.sh</code>,内容如下:

安装jetty过程,主要包括:读取配置文件,设置jetty安装目录,修改jetty的配置文件<code>etc/webdefault.xml</code>。jetty安装目录的选择包括以下三种情形:

未指定jetty安装目录,则选择默认目录进行安装

指定了jetty安装目录但是目录不存在,则创建目录并安装jetty

指定了jetty安装目录并且目录已经存在

如果配置了强制执行选项,则覆盖目录并安装jetty

如果没有配置强制执行选项,程序强制退出

部署dubbox服务的文件为<code>deploy_admin.sh</code>,内容如下:

在部署dubbox服务的过程中,有几个需要注意的问题:

当访问dubbox服务时,需要访问服务器的8080端口,由于防火墙的原因,外部可能无法访问到服务器的dubbox服务,因此需要修改防火墙的设置。本文所采用的ecs系统为centos 7,简单起见,我直接关闭了系统的防火墙。关闭防火墙的方法如下:

systemctl stop firewalld.service

这里不建议采用直接关闭防火墙的方式。

通过ansible控制远程服务器组启动jetty服务时,ansible命令执行结束以后,jetty服务也自动退出,这是我们不想看到的结果。可通过nohup命令以守护进程的方式启动jetty服务,可以解决jetty服务自动退出的问题,启动jetty命令如下:

nohup $jetty_home/bin/jetty.sh start &amp;

dubbox服务部署好了以后,可通过以下地址访问dubbox服务控制台:

注意:在vpc网络下,ip指的是slb的公网ip。

dubbox服务部署好以后,可通过以下操作登录控制台:

输入用户名密码,点击登录:

基于资源编排在专有网络环境下快速部署高可用的Dubbox服务(ZooKeeper版)

登录进去以后的dubbox控制台界面如下:

基于资源编排在专有网络环境下快速部署高可用的Dubbox服务(ZooKeeper版)

现在,我们可以使用dubbox服务了。

本章将从以下两个方面进行总结:

dubbox服务系统结构图

如何快速构建高可用dubbox服务

最终,采用zookeeper集群作为注册中心,基于资源编排快速部署出来的高可用dubbox服务的系统结构图,如下图所示:

基于资源编排在专有网络环境下快速部署高可用的Dubbox服务(ZooKeeper版)

dubbox服务的高可用,主要体现在两个方面:

注册中心的高可用

注册中心采用了zookeeper集群的方式,zookeeper集群中只要有超过半数的服务可用,dubbox服务的注册中心就可以正常工作。

dubbox服务控制台的高可用

创建两台ecs实例并分别部署dubbox控制台服务,这两台ecs挂载到一个slb上,我们可通过slb来访问dubbox控制台服务。

前面章节描述的部署过程看起来可能比较繁琐,本文的核心是快速部署,因此你可以根据下面的指导,快速部署属于你的高可用dubbox服务。四个步骤快速部署高可用dubbox服务:

下载源码

修改配置文件

运行main函数

可从本文的附件中下载源码,然后将vpc_python文件拷贝到ansible主机。

修改<code>vpc_python/config.py</code>文件,文件内容如下:

下面详细讲解配置文件中一些参数所代表的意义:

<code>vpc_id</code>

ansible主机所在的vpc id

<code>vswitch_id</code>

ansible主机所在的vswitch id

<code>zk_size</code>

zookeeper集群的大小,zookeeper集群的大小必须为奇数,且必须大于1

<code>ecs_password</code>

申请的ecs服务器的登录密码,用户名默认为root

<code>ak_id</code>

用户的ak id

<code>ak_secret</code>

用户的ak secret

<code>region_id</code>

资源栈创建的区域

<code>jetty_home</code>

jetty默认安装目录

<code>jetty_home_enforce</code>

是否强制安装jetty,f代表强制安装,其它代表非强制

<code>dubbo_root_password</code>

dubbox控制台root用户的登录密码

<code>dubbo_guest_password</code>

dubbox控制台guest用户的登录密码

用户可根据自己的需求更改配置文件。

运行<code>vpc_python/main.py</code>。函数运行完以后,高可用dubbox服务就部署好了。