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

本文涉及的产品
云服务器 ECS,每月免费额度200元 3个月
对象存储 OSS,20GB 3个月
云服务器ECS,u1 2核4GB 1个月
简介: 本文将介绍在专有网络VPC(Virtual Private Cloud)下,基于资源编排服务,快速部署高可用的Dubbox服务的过程。Dubbox服务采用的注册中心是ZooKeeper集群。做这件事情的意义在于:节约部署Dubbox的时间,降低部署Dubbox过程中出错的风险。

本文将介绍在专有网络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.”。
更多Ansible的相关知识可参考Ansible中文权威指南
Ansible的工作机制,可参考基于资源编排和 Ansible 在 VPC 下快速交付应用中“Ansible 及其运行机制”章节。
Dubbox
Dubbox在Dubbo服务的基础上添加了一些新功能,如:REST风格的远程调用、支持基于Jackson的JSON序列化、支持基于Kryo和FST的Java高效序列化实现、支持完全基于Java代码的Dubbo配置、升级Spring、升级Zookeeper等。想了解更多关于Dubbox服务内容可参考Dubbox Github
ZooKeeper
Apache ZooKeeper是Apache软件基金会的一个软件项目,他为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。ZooKeeper的架构通过冗余服务实现高可用性。本文将介绍采用ZooKeeper集群作为Dubbox服务的注册中心,来保证Dubbox服务的高可用性。更多ZooKeeper相关的知识可参考ZooKeeper Wiki

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

  • 准备Ansible主机
  • VPC网络环境下快速部署高可用的Dubbox服务
  • 总结

准备Ansible主机

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

  • 安装Ansible
  • 安装ROS SDK

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

CentOS Linux release 7.0.1406 (Core)  

这个版本的ECS已经安装了Python 2.7.5。
说明:专有网络VPC的创建链接。创建好VPC以后直接在该VPC下新建VSwitch即可。新建ECS的链接

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

安装Ansible

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

yum install ansible  

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

[root@iZ94jwkjg0sZ ansible]# ls -l
总用量 24
-rw-r--r-- 1 root root 13819 5月  25 23:49 ansible.cfg
-rw-r--r-- 1 root root   441 8月  17 17:52 hosts
drwxr-xr-x 4 root root  4096 8月  17 17:52 roles

关于Ansible的安装方式可参考Ansible Installation
注意:如果采用的是Ubuntu系统,安装Ansible过程如下:

  apt-get install ansible
  apt-get install sshpass

安装ROS SDK

ROS提供了RESTful API和SDK,本文将介绍用Python的方式来调用ROS API创建资源。
在调用ROS API之前需要安装相关的依赖。

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

pip install aliyun-python-sdk-core

使用pip安装ROS SDK:

pip install aliyun-python-sdk-ros

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

curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
python get-pip.py  

如果不了解pip,可参考维基百科)。
关于ROS SDK详细安装和使用过程可以参考阿里云资源编排服务Python SDK使用入门

VPC网络环境下快速部署高可用的Dubbox服务

本章将详解讲解Dubbox服务的部署过程。您也可以跳过此章节,直接参考如何快速构建高可用Dubbox服务快速部署Dubbox服务。

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

  • 创建资源栈
  • 编辑Inventory文件
  • 构建PlayBook
  • 执行PlayBook
  • 部署Dubbox服务

创建资源栈

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

  • 定义ROS资源模板
  • 调用ROS API,创建资源栈
  • 获取资源栈输出信息

定义ROS资源模板

本文通过调用ROS API的方式来创建资源栈。
ROS资源模板包括以下几种资源类型:

在VPC网络环境下,给InstanceGroup指定VPC和VSwtich,并保证和Anisble主机处在同一个VPC和VSwitch下,这样才能保证Ansible主机可通过ECS的私有IP来登录ECS并操控ECS实例。

定义ROS资源模板的Python文件为generate_vpc_ros_template.py,文件内容如下:

from string import Template
# define ros template
create_resources_with_parameters = '''
{
  "ROSTemplateFormatVersion": "2015-09-01",
  "Resources": {
    "InstanceGroupDubboxAdmin": {
      "Type": "ALIYUN::ECS::InstanceGroup",
      "Properties": {
        "ImageId": "centos7u2_64_40G_cloudinit_20160520.raw",
        "Password": "$ecs_password",
        "MinAmount": 2,
        "MaxAmount": 2,
        "InstanceType": "$instance_type",
        "ZoneId": "$zone_id",
        "InternetChargeType": "PayByTraffic",
        "NetworkType": "vpc",
        "InstanceName": "ecs",
        "VpcId": "$vpc_id",
        "VSwitchId": "$vswitch_id"
      }
    },
    "InstanceGroupZK": {
      "Type": "ALIYUN::ECS::InstanceGroup",
      "Properties": {
        "ImageId": "centos7u2_64_40G_cloudinit_20160520.raw",
        "Password": "$ecs_password",
        "MinAmount": 3,
        "MaxAmount": $instance_group_zk_size,
        "InstanceType": "$instance_type",
        "ZoneId": "$zone_id",
        "InternetChargeType": "PayByTraffic",
        "NetworkType": "vpc",
        "InstanceName": "zk",
        "VpcId": "$vpc_id",
        "VSwitchId": "$vswitch_id"
      }
    },
    "LoadBalance": {
      "Properties": {
        "AddressType": "internet",
        "InternetChargeType": "paybytraffic",
        "LoadBalancerName": "balancer"
      },
      "Type": "ALIYUN::SLB::LoadBalancer"
    },
    "Attachment": {
      "Properties": {
        "BackendServers": [
          {
            "ServerId": { "Fn::Select": ["0",{ "Fn::GetAtt": [ "InstanceGroupDubboxAdmin", "InstanceIds" ] }]},
            "Weight": 100
          },
           {
            "ServerId": { "Fn::Select": ["1",{ "Fn::GetAtt": [ "InstanceGroupDubboxAdmin", "InstanceIds" ] }]},
            "Weight": 100
          }
        ],
        "LoadBalancerId": {
          "Ref": "LoadBalance"
        }
      },
      "Type": "ALIYUN::SLB::BackendServerAttachment"
    },
    "Listener": {
      "Type": "ALIYUN::SLB::Listener",
      "Properties": {
          "LoadBalancerId": {
            "Ref": "LoadBalance"
          },
          "ListenerPort": $listen_port,
          "BackendServerPort": $bachend_server_port,
          "Bandwidth": -1,
          "Protocol": "http",
          "HealthCheck": {
              "HealthyThreshold": 3,
              "UnhealthyThreshold": 3,
              "Interval": 2,
              "Timeout": 5,
              "HttpCode": "http_2xx",
              "URI": "$health_check_path"
          },
          "Scheduler": "wrr"
      }
    }
  },
  "Outputs": {
    "EcsPrivateIps": {
      "Value": { "Fn::GetAtt": [ "InstanceGroupDubboxAdmin", "PrivateIps"]}
    },
    "ZKPrivateIps": {
      "Value": { "Fn::GetAtt": [ "InstanceGroupZK", "PrivateIps"]}
    },
    "LoadBalanceIp": {
      "Value": {"Fn::GetAtt": [ "LoadBalance", "IpAddress"]}
    }
   }
}
'''
# define func to generate ros template
def generate_template(**kwargs):
    template = Template(create_resources_with_parameters)
    return template.substitute(kwargs)

调用ROS API,创建资源栈

创建资源栈的Python文件为create_stack.py,文件内容如下:

from aliyunsdkcore.client import AcsClient
from aliyunsdkros.request.v20150901 import CreateStacksRequest
import generate_vpc_ros_template
import json
from config import *
# define func to create stack
def create_stack(stack_name, ak_id, ak_secret, region_id, zk_size):
    print('invoke CreateStackRequest to create instances...')
    client = AcsClient(ak_id, ak_secret, region_id)
    req = CreateStacksRequest.CreateStacksRequest()
    req.set_headers({'x-acs-region-id': region_id})
    #create vpc network resources
    template = generate_vpc_ros_template.generate_template(vpc_id = vpc_id, ecs_password = ecs_password, 
        instance_type = instance_type, zone_id = zone_id, vswitch_id = vswitch_id, 
        instance_group_zk_size = zk_size, listen_port = 8080, 
        bachend_server_port =8080, health_check_path = '/dubbo-admin/favicon.ico') 
    create_stack_body = '''
    {
        "Name": "%s",
        "TimeoutMins": %d,
        "Template": %s
    }
    ''' % (stack_name, create_timeout, template)
    req.set_content(create_stack_body)
    # get response
    response = client.get_response(req)
    # deal response
    if 201 == response[0]:
        print('Create stack succeccfully!!!')
        return json.loads(response[-1])
    else:
        print('Unexpected errors: status=%d, error=%s' % (response[0], response[-1]))
        return None
if __name__ == '__main__':
    create_stack(stack_name, ak_id, ak_secret, region_id, zk_size)

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

  1. 初始化SDK客户端对象:

    client = AcsClient(ak_id, ak_secret, region_id)

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

    req = CreateStacksRequest.CreateStacksRequest()

  3. 指定请求资源Region:

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

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

    create_stack_body = '''

    {
        "Name": "%s",
        "TimeoutMins": %d,
        "Template": %s
    }
    ''' % (stack_name, create_timeout, template)

    req.set_content(create_stack_body)

  5. 发送请求,创建资源栈:

    response = client.get_response(req)

6. 获取资源栈信息:

 # deal response
 if 201 == response[0]:
      print('Create stack succeccfully!!!')
      return json.loads(response[-1])
 else:
      print('Unexpected errors: status=%d, error=%s' % (response[0], response[-1]))
      return None

请求成功会返回资源栈的IdName信息,请求发出以后,可到ROS 控制台查看资源栈详情。

获取资源栈输出信息

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

def get_stack_outputs(stack, ak_id, ak_secret, region_id):
    print('Start to get stack output...')
    if stack is None:
        return None
    req = DescribeStackDetailRequest.DescribeStackDetailRequest()
    req.set_headers({'x-acs-region-id': region_id})
    req.set_StackName(stack['Name'])
    req.set_StackId(stack['Id'])
    client = AcsClient(ak_id, ak_secret, region_id)
    attempt = attempt_times
    wait = wait_time
    while attempt >= 0 and wait >= 0:
        response = client.get_response(req)
        if 200 == response[0]:
            resources = json.loads(response[-1])
            if (resources is None) or (not resources.has_key('Outputs')):
                    time.sleep(wait)
                    attempt = attempt - 1
                    wait = wait - interval
                    continue
            outputs = resources['Outputs']
            print('Getting stack outputs finished. outputs: ', outputs)
            return outputs
        else:
            print('Unexpected errors: status=%d, error=%s' % (response[0], response[-1]))
            return None
    print('Getting stack outputs timeout.')
    return None

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

资源栈的输出格式如下:

[{u'OutputKey': u'EcsPrivateIps', u'Description': u'No description given', u'OutputValue': [u'192.168.x.x', u'192.168.x.x']}, 
{u'OutputKey': u'ZKPrivateIps', u'Description': u'No description given', u'OutputValue': [u'192.168.x.x', u'192.168.x.x', u'192.168.x.x']}, 
{u'OutputKey': u'LoadBalanceIp', u'Description': u'No description given', u'OutputValue': u'112.74.x.x'}]

我们将以上输出定义为Outputs

编辑Inventory文件

根据上面获取的资源栈输出信息Outputs,获取Dubbox控制台服务器组的私有IP。方法如下:

def get_ecs_ips(outputs):
    for i in range(len(outputs)):
        if outputs[i]['OutputKey'] == ecs_ip_output_key:
            return outputs[i]['OutputValue']
    return None

根据上面获取的资源栈输出信息Outputs,获取ZooKeeper集群服务器组的私有IP。方法如下:

def get_zk_ips(outputs):
    for i in range(len(outputs)):
        if outputs[i]['OutputKey'] == zk_ip_output_key:
            return outputs[i]['OutputValue']
    return None

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

# define func to create inventory
def edit_hosts(host_parameters, zk_parameters):
    print 'Start edit hosts'
    host_str = ' ansible_ssh_port=%s ansible_ssh_user=%s ansible_ssh_pass=%s\n'
    with open(hosts_file, 'wb') as file:
        file.write( '[%s]\n' % host_dubbo_admin )
        for index in range(len(host_parameters)):
            file.write( ('%s'+host_str) % (host_parameters[index][0], host_parameters[index][1], host_parameters[index][2], host_parameters[index][3]) )
        file.write( '[%s]\n' % host_zookeeper )
        for index in range(len(zk_parameters)):
            file.write( ('%s'+host_str) % (zk_parameters[index][0], zk_parameters[index][1], zk_parameters[index][2], zk_parameters[index][3]) )
    print 'Edit hosts end'

执行该方法以后,生成的Inventory文件,即/etc/Ansible/hosts文件,内容如下:

[dubbo_admin]
10.169.***.*** ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=***
10.44.***.*** ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=***
[zookeeper]
10.45.***.*** ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=***
10.170.***.*** ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=***
10.170.***.*** ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=***

Inventory文件中定义了两个远程主机组,dubbo_adminzookeeper,并指定了不同主机的IP、登录协议(默认是 SSH )、登录端口、登录用户名和密码。Ansible在执行PlayBook的时候通过以上信息连接远程主机。

构建PlayBook

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

部署Dubbox控制台集群的PlayBook为vpc_dubbox_admin_playbook,结构如下:

[root@iZ94jwkjg0sZ roles]# ls -l vpc_dubbox_admin_playbook
总用量 12
drwxr-xr-x 2 501 games 4096 8月  17 17:52 files
drwxr-xr-x 2 501 games 4096 8月  17 17:52 tasks
drwxr-xr-x 2 501 games 4096 8月  17 14:20 templates

关于vpc_dubbox_admin_playbook结构的说明如下:

  • files

    • 存放install_Jdk.shinstall_Jetty.shdeploy_Admin.sh三个文件,这三个文件分别用来安装JDK、Jetty以及部署Dubbox控制台服务。
  • tasks

    • 存放要执行的yml文件 install_dubbo_admin.yml,文件内容如下:


      • name: add config
        template:

        dest: /root/config
        src: config.j2
        mode: 0600
        
      • 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,文件内容如下:

            #第一列 变量名 第二列 变量值 第三列 配置项 不同列之间用tab或者空格分开
            #jetty安装路径,当目录已经存在的时候加上f参数会强制覆盖,否则会退出安装
            JETTY_HOME {{jetty_home}} {{enforce}}
            #设置admin控制台root用户的密码
            DUBBO_ADMIN_ROOT_PASSWD {{dubbo_root}}
            #设置admin控制台guest用户的密码
            DUBBO_ADMIN_GUEST_PASSWD {{dubbo_guest}}
            #注册中心连接地址字符串
            REGISTRY_ADDRESS {{registry_address}}
            #ZooKeeper集群的IP地址
            ZK_IPS_STR {{zk_ips_str}}
            
    • 配置文件config.j2中的参数值从vpc_dubbox_zk.yml文件中获取,通过Ansible执行PlayBook的过程中会在每一台远程主机的/root目录下生成config文件,提供给install_Jdk.shinstall_Jetty.shdeploy_Admin.sh这三个脚本使用。关于vpc_dubbox_zk.yml文件,后面会提到。

部署ZooKeeper集群的PlayBook为vpc_dubbox_zookeeper_playbook,结构如下:

[root@iZ94jwkjg0sZ roles]# ls -l vpc_dubbox_admin_playbook
总用量 12
drwxr-xr-x 2 501 games 4096 8月  17 17:52 files
drwxr-xr-x 2 501 games 4096 8月  17 17:52 tasks
drwxr-xr-x 2 501 games 4096 8月  17 14:20 templates

关于vpc_dubbox_zookeeper_playbook结构的说明如下:

  • files

    • 存放install_Jdk.shinstall_ZK.sh两个文件,这两个文件分别用来安装JDK、部署ZooKeeper集群。
  • tasks

    • 存放要执行的yml文件 install_zk.yml,文件内容如下:


      • name: add config
        template:

        dest: /root/config
        src: config.j2
        mode: 0600
        
      • name: run install jdk
        script: install_Jdk.sh
      • name: run install zookeeper
        script: install_ZK.sh

  • templates

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

            #第一列 变量名 第二列 变量值 第三列 配置项 不同列之间用tab或者空格分开
            #jetty安装路径,当目录已经存在的时候加上f参数会强制覆盖,否则会退出安装
            JETTY_HOME {{jetty_home}} {{enforce}}
            #设置admin控制台root用户的密码
            DUBBO_ADMIN_ROOT_PASSWD {{dubbo_root}}
            #设置admin控制台guest用户的密码
            DUBBO_ADMIN_GUEST_PASSWD {{dubbo_guest}}
            #注册中心连接地址字符串
            REGISTRY_ADDRESS {{registry_address}}
            #ZooKeeper集群的IP地址
            ZK_IPS_STR {{zk_ips_str}}
            
    • 配置文件config.j2中的参数值从vpc_dubbox_zk.yml文件中获取,通过Ansible执行PlayBook的过程中会在每一台远程主机的/root目录下生成config文件,提供给install_Jdk.shinstall_ZK.sh使用。关于vpc_dubbox_zk.yml文件,后面会说明。

这两个PlayBook构建好了以后,可上传到阿里云OSS。在执行脚本的时候需要用到这两个PlayBook,可以通过wget命令从阿里云OSS上下载,然后直接使用。

执行PlayBook

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

  • 生成Ansible可执行文件
  • 下载PlayBook
  • 执行PlayBook

生成Ansible可执行文件

我们需要通过Ansible执行vpc_dubbox_zk.yml文件来运行我们构建好的两个PlayBook。
vpc_dubbox_zk.yml文件的生成,需要分两步进行:

  • 定义文件模板
  • 生成文件

定义vpc_dubbox_zk.yml文件模板的Python文件为deploy_vpc_dubbox.py,文件内容如下:

from string import Template
create_hosts_with_parameters = '''
- name: deploy dubbox service
  hosts: $zookeeper
  vars:
    - jetty_home: $jetty_home
    - enforce: $jetty_home_enforce
    - dubbo_root: $dubbo_root_password
    - dubbo_guest: $dubbo_guest_password
    - registry_address: $registry_address 
    - zk_ips_str: $zk_ips_str
  roles:
    - $zookeeper_pb_name
    
- name: deploy dubbox service
  hosts: $dubbo_admin
  vars:
    - jetty_home: $jetty_home
    - enforce: $jetty_home_enforce
    - dubbo_root: $dubbo_root_password
    - dubbo_guest: $dubbo_guest_password
    - registry_address: $registry_address 
    - zk_ips_str: $zk_ips_str
  roles:
    - $dubbo_admin_pb_name
'''
#define func to define redis playbook template
def create_playbook(**kwargs):
    template = Template(create_hosts_with_parameters)
    return template.substitute(kwargs)

生成vpc_dubbox_zk.yml文件,方法如下:

# define func to create playbook init config
def create_pb_init(registry_address, zk_ips_str):
    print('Start to edit playbook init config...')
    with open(ansible_dir + pb_file_name, 'wb') as file_pb:
        playbook = generate_playbook_template.create_playbook(dubbo_admin=host_dubbo_admin, zookeeper=host_zookeeper, jetty_home=jetty_home, 
            jetty_home_enforce=jetty_home_enforce, dubbo_root_password=dubbo_root_password, dubbo_guest_password=dubbo_guest_password,
            registry_address=registry_address, zk_ips_str=zk_ips_str, dubbo_admin_pb_name=dubbo_admin_pb_name, zookeeper_pb_name=zookeeper_pb_name)
        file_pb.write(playbook)
    print('Editting pb_init is finished.')

生成的vpc_dubbox_zk.yml文件的内容如下:

- name: deploy dubbox service
  hosts: zookeeper
  vars:
    - jetty_home: /opt/jetty
    - enforce: f
    - dubbo_root: ***
    - dubbo_guest: ***
    - registry_address: 192.168.***.***:2181?backup=192.168.***.***:2181,192.168.***.***:2181
    - zk_ips_str: 192.168.***.***,192.168.***.***,192.168.***.***
  roles:
    - vpc_dubbox_zookeeper_playbook

- name: deploy dubbox service
  hosts: dubbo_admin
  vars:
    - jetty_home: /opt/jetty
    - enforce: f
    - dubbo_root: root
    - dubbo_guest: guest
    - registry_address: 192.168.***.***:2181?backup=192.168.***.***:2181,192.168.***.***:2181
    - zk_ips_str: 192.168.***.***,192.168.***.***,192.168.***.***
  roles:
    - vpc_dubbox_admin_playbook

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

  • hosts

    • 远程主机组名称,和Inventory文件中的远程主机组相对应。此文件说明要连接的主机组有两个。
  • vars

    • 配置文件config中的参数,提供给install_Jdk.shinstall_Jetty.shdeploy_Admin.shinstall_ZK.sh使用。
  • roles

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

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

下载PlayBook

前面的章节构建PlayBook中提出,构建好PlayBook后会传到阿里云OSS上,然后通过wget命令下载到/etc/ansible/roles目录下。下载PlayBook的方法如下:

def download_playbook():
    for url in playbook_url:
        file_name = url.split('/')[-1]
        command_wget = 'wget -P ' + playbook_dir + ' ' + url
        subprocess.call(command_wget, shell = True)
        command_tar = 'tar zxf ' + playbook_dir + file_name + ' -C ' + playbook_dir
        subprocess.call(command_tar, shell = True)
        command_rm = 'rm -rf ' + playbook_dir + file_name
        subprocess.call(command_rm, shell = True)
        

执行playbook

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

OSX10111-0c4de9cb8aea:dubbox wujin.lhr$ ssh root@112.74.205.137
    The authenticity of host '112.74.205.137 (112.74.205.137)' can't be established.
    ECDSA key fingerprint is SHA256:bbDuVh6dQYDQo/X+Qzh52VGAxBFpGSqVG0jVNCB/9cE.
    Are you sure you want to continue connecting (yes/no)?

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

# define func to confirm ssh login before execute ansible
def confirm_ssh_login(all_ips):
    print('Start to confirm ssh login to all nodes...')
    if len(all_ips) == 0:
        print('Host_ips is empty')
        return
    for ip in all_ips:
        child = pexpect.spawn('ssh root@' + ip)
        ret_1 = child.expect(['Are you sure you want *', 'Password*', 'root@*', pexpect.EOF])
        if 0 == ret_1:
            child.sendline('yes')
            ret_2 = child.expect(['Password*', 'root@*', pexpect.EOF])
            if 0 == ret_2 or 1 == ret_2:
                print('Confirm ' + ip + ' ok!')
                child.sendintr()
                continue
            else:
                print('Confirm ' + ip + ' failed!')
        elif 1 == ret_1 or 2 == ret_1:
            print('Confirm ' + ip + ' ok!')
            child.sendintr()
        else:
            print('Confirm ' + ip + ' failed!')
    print('Confirm ssh login finished!')

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

pip install pexpect

VPC网络环境下未给ECS分配公网IP,导致每台ECS无法下载安装包,但是在安装JDK、Jetty以及部署Dubbox Admin和Zookeeper集群的时候需要这些安装包。因为Ansible主机配有公网IP,所以可以将安装包先下载到Ansible主机,又因为Ansible主机和每台ECS在同一个VSwitch下面,可以通过scp命令将安装包从Ansible主机传到每台ECS上。具体操作过程如下:

  1. 首先将JDK、Jetty、Dubbox Admin以及ZooKeeper安装包上传至阿里云OSS,获取安装包的下载地址。
  2. 在Python文件中填入安装包的下载地址,运行Python脚本,下载安装包至Ansible主机。方法如下:

    def wget_files():

    if not os.path.exists(wget_file_path):
        os.makedirs(wget_file_path)
    subprocess.call('wget -P ' + wget_file_path + ' ' + jdk_path, shell = True)
    subprocess.call('wget -P ' + wget_file_path + ' ' + jetty_path, shell = True)
    subprocess.call('wget -P ' + wget_file_path + ' ' + dubbo_admin_path, shell = True)
    subprocess.call('wget -P ' + wget_file_path + ' ' + zookeeper_path, shell = True)
            
  3. 通过scp命令将安装包拷贝到每台ECS。方法如下:

    def scp_files_from_ansible_host_to_ecs_zk(host_ips, zk_ips):

    scp_password_info = 'root@%s\'s password:' 
    scp_command_ecs = 'scp ' + wget_file_path + 'dubbo-admin-2.8.4.war ' + wget_file_path + 'jdk-8u101-linux-x64.rpm ' + wget_file_path + 'jetty-distribution-8.1.19.v20160209.tar.gz root@%s:/root'
    scp_command_zk = 'scp ' + wget_file_path + 'jdk-8u101-linux-x64.rpm ' + wget_file_path + 'zookeeper-3.4.6.tar.gz root@%s:/root'
    if host_ips is None or len(host_ips) == 0:
        print 'Host ips is None,exit!'
        return None
    if zk_ips is None or len(zk_ips) == 0:
        print 'ZK ips is None,exit!'
        return None
    for ip in host_ips:
        scp = pexpect.spawn(scp_command_ecs % ip)
        i = scp.expect([scp_password_info % ip, pexpect.EOF])
        if i == 0:
            scp.sendline(ecs_password)
            scp.expect(pexpect.EOF, timeout=None)
        else:
            print 'Scp files to' + ip + 'failed!'
    for ip in zk_ips:
        scp = pexpect.spawn(scp_command_zk % ip)
        i = scp.expect([scp_password_info % ip, pexpect.EOF])
        if i == 0:
            scp.sendline(ecs_password)
            scp.expect(pexpect.EOF, timeout=None)
        else:
            print 'Scp files to' + ip + 'failed!'
    
  4. 通过Ansible,执行PlayBook。方法如下:

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

运行Ansible以后会进行Dubbox服务的部署过程。

部署Dubbox服务

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

  • 搭建ZooKeeper集群
  • 搭建Dubbox控制台集群

搭建ZooKeeper集群

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

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

  • 安装JDK
  • 搭建ZooKeeper集群
安装JDK

因为ZooKeeper的运行需要Java环境,所以需要先安装JDK。安装JDK的脚本为install_Jdk.sh,文件内容如下:

#!/bin/bash
#日志时间格式
DATE="date +'%Y-%m-%d %H:%M:%S'"
#检查java环境是否存在
if which java 2>/dev/null; then
        echo $(eval $DATE) " java already exits" >> ~/install_dubbox.log
else
        #wget jdk安装包
        #wget http://dubbo.oss-cn-shenzhen.aliyuncs.com/jdk-8u101-linux-x64.rpm
        #echo $(eval $DATE) " wget jdk success" >> ~/install_dubbox.log
        rpm -ivh jdk-8u101-linux-x64.rpm
        rm -rf jdk-8u101-linux-x64.rpm
fi
#检查java环境是否安装成功
if which java 2>/dev/null; then
        echo $(eval $DATE) " install jdk8 success" >> ~/install_dubbox.log
else
        echo $(eval $DATE) " install jdk8 failed" >> ~/install_dubbox.log

安装JDK过程中,首先需要检查当前ECS是否存在Java环境,存在就跳过安装过程,反之则安装。
声明:JDK安装包请从Oracle官网下载,并下载本文指定的JDK版本(jdk-8u101-linux-x64.rpm)。从本文链接中下载JDK带来的任何法律问题,和本文作者无关。

搭建ZooKeeper集群

搭建ZooKeeper集群的脚本为install_ZK.sh,内容如下:

#!/bin/sh
#日志时间格式
DATE="date +'%Y-%m-%d %H:%M:%S'"
#download zk
#wget 'http://dubbo.oss-cn-shenzhen.aliyuncs.com/zookeeper-3.4.6.tar.gz'
#解压zk到/opt目录
tar -zxvf zookeeper-3.4.6.tar.gz -C /opt
#设置软链接
ln -s /opt/zookeeper-3.4.6 /opt/zookeeper
#复制zoo.cfg文件
cp /opt/zookeeper/conf/zoo_sample.cfg /opt/zookeeper/conf/zoo.cfg
#删除压缩包
rm -rf zookeeper-3.4.6.tar.gz
#读取配置文件内容,给变量赋初值
while read line
do
    #过滤掉注释行
    if [ ! "`echo $line|grep '#'`" ]; then
        varname=`echo $line|awk '{print $1}'`
        varvalue=`echo $line|awk '{print $2}'`
        varconfig=`echo $line|awk '{print $3}'`
        eval $varname=$varvalue
        eval $varname"_CONFIG"=$varconfig
    fi
done < ~/config
mkdir -p '/opt/zookeeper/data'
#修改配置文件
sed -i -e 's/^dataDir=.*/dataDir=\/opt\/zookeeper\/data/' /opt/zookeeper/conf/zoo.cfg
ZK_IPS_STR=${ZK_IPS_STR//,/ }
init_id=1
#获取本机ip
SELF_IP=`ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"`
for ip in $ZK_IPS_STR
do
    echo "server.$init_id=$ip:2888:3888" >> /opt/zookeeper/conf/zoo.cfg
    #创建myid文件,标识本机id号
    if [[ $SELF_IP == *$ip* ]]; then
        echo $init_id >  "/opt/zookeeper/data/myid"
    fi
    init_id=$((init_id+1))    
done
#启动zk
nohup /opt/zookeeper/bin/zkServer.sh start &
sleep 10
#centos 7 关闭防火墙
systemctl stop firewalld.service
#查看当前是否存在zookeeper进程
ZK_ID=`ps -ef |grep zookeeper |grep -v grep |awk '{print $2}'`
if [ ! "$ZK_ID" ]; then
    echo $(eval $DATE) " start zookeeper failed" >> ~/install_dubbox.error.log
else
    echo $(eval $DATE) " start zookeeper success" >> ~/install_dubbox.log
fi
#删除配置文件
rm -rf ~/config

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

tickTime=2000  
dataDir=/opt/zookeeper/data  
clientPort=2181  
initLimit=5  
syncLimit=2  
server.1=slave-01:2888:3888  
server.2=slave-02:2888:3888  
server.3=slave-03:2888:3888  

上述文件,配置了三台机器的ZooKeeper集群。在dataDir目录下,创建一个myid文件,里面内容为一个数字,用来标识当前主机号。
更多关于ZooKeeper集群配置的知识,可参考Running Replicated ZooKeeper

搭建Dubbox控制台集群

由于Dubbox控制台需要运行在Jetty容器上,Jetty容器的运行又需要有Java环境,因此部署Dubbox控制台之前,需要先安装JDK和Jetty。

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

  • 安装JDK
  • 安装Jetty
  • 部署Dubbox控制台
安装JDK

安装JDK的文件为install_Jdk.sh,和上述过程安装JDK相同,此处不再重复。

安装Jetty

安装Jetty的文件为install_Jetty.sh,内容如下:

#!/bin/bash
#jetty默认安装目录
JETTY_HOME_DEFAULT="/opt/jetty"
#日志时间格式
DATE="date +'%Y-%m-%d %H:%M:%S'"
#安装jetty
#wget http://dubbo.oss-cn-shenzhen.aliyuncs.com/jetty-distribution-8.1.19.v20160209.tar.gz
#echo $(eval $DATE) " wget jetty success" >> ~/install_dubbox.log
#解压
tar zxf jetty-distribution-8.1.19.v20160209.tar.gz
echo $(eval $DATE) " tar zxf jetty success" >> ~/install_dubbox.log
#删除压缩包
rm -f jetty-distribution-8.1.19.v20160209.tar.gz
echo $(eval $DATE) " rm jetty.tgz success" >> ~/install_dubbox.log
#读取配置文件内容,给变量赋初值
while read line
do
        #过滤掉注释行
        if [ ! "`echo $line|grep '#'`" ]; then
                varname=`echo $line|awk '{print $1}'`
                varvalue=`echo $line|awk '{print $2}'`
                varconfig=`echo $line|awk '{print $3}'`
                eval $varname=$varvalue
                eval $varname"_CONFIG"=$varconfig
        fi
done < ~/config
#JETTY_HOME未配置,选择默认配置JETTY_HOME_DEFAULT
if [ ! -n "$JETTY_HOME" ]; then
        JETTY_HOME=$JETTY_HOME_DEFAULT
        rm -rf $JETTY_HOME
        mkdir -p $JETTY_HOME
        echo $(eval $DATE) " JETTY_HOME采用默认设置 $JETTY_HOME" >> ~/install_dubbox.log
#如果目录不存在,创建目录
elif [ ! -d "$JETTY_HOME" ]; then
        mkdir -p $JETTY_HOME
        echo $(eval $DATE) " 创建JETTY_HOME新目录 $JETTY_HOME" >> ~/install_dubbox.log       
#如果目录已经存在,并且配置了强制执行,则覆盖目录
elif [ "$JETTY_HOME_CONFIG" = "f" ]; then
        rm -rf $JETTY_HOME
        mkdir -p $JETTY_HOME
        echo $(eval $DATE) " 强制覆盖已存在的JETTY_HOME $JETTY_HOME" >> ~/install_dubbox.log
#如果目录已经存在,并且没有配置强制执行,退出程序
else
        echo $(eval $DATE) " $JETTY_HOME 已经存在,未选择强制覆盖,请重新设置JETTY_HOME或在配置文件中配
置强制执行选项:f" >> ~/install_dubbox.log
        #退出程序
        exit
        echo $(eval $DATE) " 程序退出" >> ~/install_dubbox.log
fi
#移动jetty到JETTY_HOME
mv jetty-distribution-8.1.19.v20160209/* $JETTY_HOME
rm -rf jetty-distribution-8.1.19.v20160209
echo $(eval $DATE) " mv jetty  success" >> ~/install_dubbox.log
#将jetty配置文件/etc/webdefault.xml中的属性dirAllowed值设置为false
cd $JETTY_HOME/etc
#确认行数
NUMBER=`grep -n "<param-name>dirAllowed</param-name>" webdefault.xml | cut  -d  ":"  -f  1`
sed -i -e "$[++NUMBER]s/.*/<param-value>false<\/param-value>/" webdefault.xml
echo $(eval $DATE) " set dirAllowed to false success" >> ~/install_dubbox.log
#查看jetty服务是否开启,即系统已经安装了jetty并已经开启
JETTY_PROCESS_ID=`ps -fe|grep jetty |grep -v grep |awk '{print $2}'`
#未开启jetty服务
if [ ! "$JETTY_PROCESS_ID" ]; then
        $JETTY_HOME/bin/jetty.sh start
        echo $(eval $DATE) " start jetty" >> ~/install_dubbox.log
else
        kill -9 $JETTY_PROCESS_ID
        echo $(eval $DATE) " stop jetty" >> ~/install_dubbox.log
        $JETTY_HOME/bin/jetty.sh start
        echo $(eval $DATE) " start jetty" >> ~/install_dubbox.log
fi
#查看jetty服务是否开启
JETTY_PROCESS_ID=`ps -fe|grep jetty |grep -v grep |awk '{print $2}'`
if [ ! "$JETTY_PROCESS_ID" ]; then
        echo $(eval $DATE) " install jetty failed" >> ~/install_dubbox.error.log
else
     echo $(eval $DATE) " install jetty success" >> ~/install_dubbox.log
     kill -9 $JETTY_PROCESS_ID
     echo $(eval $DATE) " stop jetty" >> ~/install_dubbox.log
fi

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

  • 未指定Jetty安装目录,则选择默认目录进行安装
  • 指定了Jetty安装目录但是目录不存在,则创建目录并安装Jetty
  • 指定了Jetty安装目录并且目录已经存在

    • 如果配置了强制执行选项,则覆盖目录并安装Jetty
    • 如果没有配置强制执行选项,程序强制退出
部署Dubbox控制台

部署Dubbox服务的文件为deploy_Admin.sh,内容如下:

#!/bin/sh

#默认jetty安装目录
JETTY_HOME_DEFAULT="/opt/jetty"
#默认root用户密码
DUBBO_ADMIN_ROOT_PASSWD_DEFAULT=root
#默认guest用户密码
DUBBO_ADMIN_GUEST_PASSWD_DEFAULT=guest
#日志时间格式
DATE="date +'%m-%d-%Y %H:%M:%S'"

#读取配置文件内容,给变量赋初值
while read line
do
    #过滤掉注释行
    if [ ! "`echo $line|grep '#'`" ]; then
        varname=`echo $line|awk '{print $1}'`
        varvalue=`echo $line|awk '{print $2}'`
        varconfig=`echo $line|awk '{print $3}'`
        eval $varname=$varvalue
        eval $varname"_CONFIG"=$varconfig
    fi
done < ~/config
#JETTY_HOME未配置,选择默认配置JETTY_HOME_DEFAULT
if [ ! -n "$JETTY_HOME" ]; then
        JETTY_HOME=$JETTY_HOME_DEFAULT
#如果目录已经存在,并且没有要求强制覆盖
elif [ -d "$JETTY_HOME" ]; then
        if [ "$JETTY_HOME_CONFIG" != "f" ]; then
            echo $(eval $DATE) " $JETTY_HOME 已经存在,未选择强制覆盖,请重新设置JETTY_HOME或在配置文件中配置强制执行选项:f" >> ~/install_dubbox.log
            #退出程序
            echo $(eval $DATE) " 程序退出" >> ~/install_dubbox.log
            exit
    fi
fi

#检测admin root用户密码是否设置
if [ ! $DUBBO_ADMIN_ROOT_PASSWD ]; then
        echo $(eval $DATE) " 未设置admin root用户的密码,采用默认密码 $DUBBO_ADMIN_ROOT_PASSWD_DEFAULT" >> ~/install_dubbox.log
        DUBBO_ADMIN_ROOT_PASSWD=$DUBBO_ADMIN_ROOT_PASSWD_DEFAULT
fi

#检测admin guest用户密码是否设置
if [ ! $DUBBO_ADMIN_GUEST_PASSWD ]; then
        echo $(eval $DATE) " 未设置admin guest用户的密码,采用默认密码 $DUBBO_ADMIN_GUEST_PASSWD_DEFAULT" >> ~/install_dubbox.log
        DUBBO_ADMIN_GUEST_PASSWD=$DUBBO_ADMIN_GUEST_PASSWD_DEFAULT
fi

#从oss上下载dubbo-admin的war包
#wget http://dubbo.oss-cn-shenzhen.aliyuncs.com/dubbo-admin-2.8.4.war
#echo $(eval $DATE) " wget dubbo-admin success" >> ~/install_dubbox.log

#将war包部署到jetty上
mv dubbo-admin-2.8.4.war $JETTY_HOME/webapps/dubbo-admin.war
echo $(eval $DATE) " mv dubbo-admin.war to webapps" >> ~/install_dubbox.log

#修改配置文件
mkdir $JETTY_HOME/webapps/dubbo-admin
cd $JETTY_HOME/webapps/dubbo-admin
jar xf ../dubbo-admin.war
cd $JETTY_HOME/webapps/dubbo-admin/WEB-INF

#配置admin注册监听文件
sed -i -e "s/^dubbo.registry.address.*/dubbo.registry.address=zookeeper:\/\/$REGISTRY_ADDRESS/" dubbo.properties
echo $(eval $DATE) " set registry to redis" >> ~/install_dubbox.log

#设置root用户密码
sed -i -e "s/^dubbo.admin.root.password.*/dubbo.admin.root.password=$DUBBO_ADMIN_ROOT_PASSWD/" dubbo.properties
echo $(eval $DATE) " set user root passwd" >> ~/install_dubbox.log
#设置guest用户密码
sed -i -e "s/^dubbo.admin.guest.password.*/dubbo.admin.guest.password=$DUBBO_ADMIN_GUEST_PASSWD/" dubbo.properties
echo $(eval $DATE) " set user guest passwd" >> ~/install_dubbox.log

cd $JETTY_HOME/webapps/dubbo-admin
jar cf dubbo-admin.war *
mv dubbo-admin.war $JETTY_HOME/webapps/
rm -rf $JETTY_HOME/webapps/dubbo-admin

#启动jetty
nohup $JETTY_HOME/bin/jetty.sh start &
echo $(eval $DATE) " start jetty" >> ~/install_dubbox.log

#关闭centos7的防火墙
systemctl stop firewalld.service
sleep 30

CODE=`curl -I -m 10 -o /dev/null -s -w %{http_code}  -u root:$DUBBO_ADMIN_ROOT_PASSWD http://localhost:8080/dubbo-admin/`
echo $(eval $DATE) " return http status code: $CODE" >> ~/install_dubbox.log
if [ $CODE = 200 ]; then
    echo $(eval $DATE) " admin控制台启动成功" >> ~/install_dubbox.log
else
    echo $(eval $DATE) " admin控制台启动失败" >> ~/install_dubbox.error.log
fi
rm -rf ~/config

部署Dubbox服务控制台的过程,主要包括:先将Dubbox服务部署到Jetty上,然后修改dubbo.properties文件的方式来设置Dubbox服务注册中心为ZooKeeper集群的方式,并设置Dubbox服务控制台的登录密码。Dubbox服务注册中心的选择,可参考Dubbo用户指南

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

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

    systemctl stop firewalld.service

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

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

    nohup $JETTY_HOME/bin/jetty.sh start &

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

http://ip:8080/dubbo-admin

注意:在VPC网络下,ip指的是SLB的公网IP。

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

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

图片

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

图片

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

总结

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

  • Dubbox服务系统结构图
  • 如何快速构建高可用Dubbox服务

Dubbox服务系统结构图

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

图片

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

  • 注册中心的高可用

    • 注册中心采用了ZooKeeper集群的方式,ZooKeeper集群中只要有超过半数的服务可用,Dubbox服务的注册中心就可以正常工作。
  • Dubbox服务控制台的高可用

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

注意:生产环境中应该将SLB放在VPC网络环境内,本文中为了测试方便,把SLB放在VPC网络环境外。若需要修改SLB的网络环境,只需修改ROS资源模板

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

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

  • 准备Ansible主机
  • 下载源码
  • 修改配置文件
  • 运行main函数
准备Ansible主机

这个过程和前面章节的准备Ansible主机相同,这里不再重复。

下载源码

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

修改配置文件

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

#define stack name
stack_name = 'vpc_dubbox_zookeeper'
# define stack creation timeout(minutes)
create_timeout = 60
#vpc parameter
vpc_id = '******'
vswitch_id = '******'
#zookeeper cluster size
zk_size = 3
#ecsgroup parameters
ecs_password = '******'
instance_type =  'ecs.s2.large'
#ros ak id
ak_id = '******'
#ros ak secret
ak_secret = '******'
#ros region id
region_id = 'cn-shenzhen'
#zone id
zone_id = 'cn-shenzhen-a'
#set jetty path
jetty_home = '/opt/jetty'
#if jetty_home exists, choose f to overlap
jetty_home_enforce = 'f'
#dubbo admin root password
dubbo_root_password = '******'
#dubbo admin guest password
dubbo_guest_password = '******'

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

  • vpc_id

    • Ansible主机所在的VPC ID
  • vswitch_id

    • Ansible主机所在的VSwitch ID
  • zk_size

    • ZooKeeper集群的大小,ZooKeeper集群的大小必须为奇数,且必须大于1
  • ecs_password

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

    • 用户的ak id
  • ak_secret

    • 用户的ak secret
  • region_id

    • 资源栈创建的区域
  • jetty_home

    • jetty默认安装目录
  • jetty_home_enforce

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

    • Dubbox控制台root用户的登录密码
  • dubbo_guest_password

    • Dubbox控制台guest用户的登录密码

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

运行main函数

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

目录
相关文章
|
14天前
|
监控 负载均衡 Cloud Native
ZooKeeper分布式协调服务详解:面试经验与必备知识点解析
【4月更文挑战第9天】本文深入剖析ZooKeeper分布式协调服务原理,涵盖核心概念如Server、Client、ZNode、ACL、Watcher,以及ZAB协议在一致性、会话管理、Leader选举中的作用。讨论ZooKeeper数据模型、操作、会话管理、集群部署与管理、性能调优和监控。同时,文章探讨了ZooKeeper在分布式锁、队列、服务注册与发现等场景的应用,并在面试方面分析了与其它服务的区别、实战挑战及解决方案。附带Java客户端实现分布式锁的代码示例,助力提升面试表现。
30 2
|
25天前
|
存储 安全 网络安全
云端防御战线:云计算环境下的网络安全与信息保护
在信息技术迅猛发展的今天,云计算作为支撑数字转型的重要基石,其安全性牵动着企业生存与发展的命脉。本文深入探讨了云计算环境中面临的安全威胁和挑战,并提出了一系列创新的安全策略和技术解决方案。通过综合分析公有云、私有云以及混合云服务模型中的安全需求,文章构建了一个多层次、全方位的网络安全防护体系。此外,针对数据加密、身份验证、访问控制等关键技术进行了深入剖析,旨在为读者提供一套系统的信息安全保护指南,确保在享受云计算带来的便利时,数据和资源的安全性不被妥协。
41 8
|
15天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
39 6
|
4天前
|
机器学习/深度学习 人工智能 安全
云端防御战线:云计算环境中的网络安全策略
【4月更文挑战第22天】 在数字化时代,云计算已成为企业运营的关键基础设施。然而,随着其广泛应用,云服务也成为了网络攻击者的主要目标。本文深入探讨了云计算环境下的网络安全挑战,分析了云服务提供者和使用者面临的安全威胁,并提出了综合性的安全策略。这些策略不仅包括传统的加密和身份验证技术,还涉及更先进的入侵检测系统、行为分析和机器学习算法。文章旨在为读者提供一个关于如何在享受云计算带来的便利同时确保数据和操作安全的综合指南。
|
1天前
|
云安全 安全 网络安全
云端防御战线:构建云计算环境下的网络安全体系
【4月更文挑战第25天】 随着企业数字化转型的加速,云计算以其灵活性、成本效益和可扩展性成为众多组织的首选技术平台。然而,云服务的广泛采用也带来了前所未有的安全挑战,特别是在数据保护、隐私合规以及网络攻击防护等方面。本文将深入探讨云计算环境中的网络安全策略,从云服务模型出发,分析不同服务层次的安全责任划分,并针对网络威胁提出综合性的防御措施。此外,文中还将讨论信息加密、身份验证、入侵检测等关键技术在维护云安全中的作用,以期为读者提供一套全面的云安全解决方案框架。
|
2天前
|
监控 安全 网络安全
云端防御战线:云计算环境下的网络安全与信息保护策略
【4月更文挑战第24天】 随着企业数字化转型的加速,云计算作为提供灵活、可扩展资源的关键平台,其安全性已成为企业关注的焦点。然而,云服务的共享性和开放性给传统的网络安全防护带来了新的挑战。本文将探讨云计算环境中面临的安全威胁,并针对这些威胁提出相应的防护措施和最佳实践,以期为信息安全管理者提供参考和指导。
5 0
|
3天前
|
存储 监控 安全
云端防御战线:云计算环境下的网络安全策略与实践
【4月更文挑战第23天】在数字化转型的浪潮中,云计算已成为推动企业敏捷性、可扩展性和成本效率的关键因素。然而,随着数据和服务迁移至云端,传统的网络边界逐渐模糊,给网络安全带来了前所未有的挑战。本文探讨了在多租户云环境中维护信息安全的先进策略和技术,分析了云服务模型(IaaS, PaaS, SaaS)特有的安全风险,并提出了一系列针对性的安全措施和最佳实践。通过深入讨论身份与访问管理、数据加密、入侵检测系统以及合规性监控等关键技术,本文旨在为读者提供一套全面的云计算安全防护框架。
5 0
|
4天前
|
监控 安全 网络安全
云端防御战线:云计算环境下的网络安全与信息保护策略
【4月更文挑战第22天】随着企业和个人用户对云服务的依赖日益加深,云计算环境的安全性成为信息技术领域关注的焦点。本文深入探讨了云计算平台面临的安全威胁、信息安全管理的挑战以及前沿防御技术。通过分析数据加密、身份验证、入侵检测等关键技术在云服务中的应用,提出了一个多层次、综合性的网络安全策略框架。此框架旨在为云服务提供商和使用者提供一套实用的安全保障措施,确保云资源的安全高效运营。
|
6天前
|
存储 安全 网络安全
云端防御策略:融合云服务与网络安全的未来之路
【4月更文挑战第20天】 随着企业数字化转型的加速,云计算已成为支撑现代业务架构的关键。然而,伴随其发展的网络安全威胁也不断演变,对信息安全提出更高要求。本文将深入探讨在动态云环境中实现网络安全防护的策略和技术,包括最新的加密技术、身份验证机制以及入侵检测系统等。通过分析当前云服务中的安全挑战,并结合前沿的网络安全技术,旨在为读者提供一个关于如何在享受云计算便利的同时保障数据安全的全面视角。
|
7天前
|
存储 安全 网络安全
构筑安全之盾:云计算环境下的网络安全与信息保护策略
【4月更文挑战第19天】随着云计算技术的飞速发展,企业和个人越来越依赖于云服务来存储、处理和交换数据。然而,这种便利性背后隐藏着潜在的安全风险。本文深入探讨了在云计算背景下,如何通过综合性的安全措施和策略来强化网络安全防护,确保数据的完整性、可用性和机密性。我们将分析当前面临的主要安全挑战,并基于最新的技术进展提出相应的解决方案,以期达到有效防御外部威胁和内部漏洞的目的。
16 4

推荐镜像

更多