开发者社区> 箫竹Aaron> 正文

基于资源编排和 Ansible 在 VPC 下快速交付应用

简介: 阿里云资源编排服务(ROS)为我们快速搭建和整合云计算资源环境提供一个低成本、标准化的方案。基于ROS提供的能力,我们所要做的就是将所需的资源以资源模板的形式进行定义,进而实现对所定义云资源的快速生产。除此之外,ROS 将应用交付和资源释放的过程也进行了简化。 用户基于 ROS 交付应用可以有两种
+关注继续查看

阿里云资源编排服务(ROS)为我们快速搭建和整合云计算资源环境提供一个低成本、标准化的方案。基于ROS提供的能力,我们所要做的就是将所需的资源以资源模板的形式进行定义,进而实现对所定义云资源的快速生产。除此之外,ROS 将应用交付和资源释放的过程也进行了简化。

用户基于 ROS 交付应用可以有两种途径:一种是通过 ROS 搭建资源环境,然后登陆云主机 ECS,手动实现对应用的部署和维护操作;另一种是利用文章基于资源编排一键交付应用中提到的 Cloud-Init 机制,实现对应用的一键交付。但是,不管利用哪种方式,它们都将面临同一个问题:随着 ECS 数量的增多和应用部署复杂度的增大,应用部署和维护的成本会相应的增大。那么如何在降低构建应用操作成本的同时,实现对应用的快速交付呢?这里就要使用自动化运维管理工具 Ansible

可以说,ROS 帮助我们快速搭建了资源环境,Ansible 可帮助我们在已搭建好的资源环境中实现了应用的快速交付。

本文将介绍利用 ROS 和 Ansible 实现对应用的快速交付。为了更好的理解应用交付的整个实现过程,本文首先对 Ansible 及其运行机制进行简单的介绍,然后讲述基于 ROS 和 Ansible 快速交付应用的过程,最后以搭建 Redis 集群作为示例,展示整个应用交付过程,本文大致流程如下:

  • Ansible 及其运行机制
  • 基于 ROS 和 Ansible 快速交付应用
  • 基于 ROS 和 Ansible 快速搭建 Redis 集群

Ansible 及其运行机制

Ansible 是一个基于 Python paramiko 开发的、分布式的、需客户端的、轻量级的自动化运维管理工具,它可以实现自动化部署应用、配置、执行 task 等工作。面对多台服务器的运维工作时,它大大简化了运维人员的工作量,降低了应用的部署和交付成本。

Ansible 使用 YMAL 语法及 Jinja2 模板语言,采用 paramiko 协议库,通过 SSH 或者 ZeroMQ 等方式连接工作主机,进而实现对远程主机的控制和维护。Ansible 一般每两个月出一个发行版本。

Ansible的运行机制:管理节点 Master 利用存放节点信息的 Inventory 文件将 Ansible 模块通过 SSH 协议(或者 Kerberos、LDAP)推送到被管理节点,然后执行 Playbooks,执行结束后自动删除,如下图所示:
ansible_work
由上图可知,Ansible主要有五部分组成:

  • Master:Ansible 的控制节点核心
  • Inventory:定义 Ansible 管理主机的清单
  • Playbooks:定义 Ansible 执行任务文件及其配置文件
  • Modules:包括 Ansible 自带的核心模块及自定义模块
  • Plugins:完成模块功能的补充

基于 ROS 和 Ansible 快速交付应用

在了解了 Ansible 的运行机制后,接下来将介绍利用 ROS 快速生产应用运行环境,并结合 Ansible 实现对应用的快速交付,大致流程如下:
ros_and_ansible

  • 安装 ROS SDK 和 Ansible
  • 基于 ROS 创建资源栈,搭建资源环境
  • 获取主机信息,并创建 Inventory 文件,获取 Playbook
  • 执行 Playbook,完成应用的快速交付基于 Ansible 快速部署应用

值得注意的是,本文介绍的快速交付应用是在 VPC 环境下进行的,并且过是以 python 的形式执行的,所以在开始之前,需要有一台可以访问公网的 ECS 作为 Master,以执行所有的 python 程序。下面详细介绍基于 ROS 和 Ansible 快速交付应用的流程。

安装 ROS SDK 和 Ansible

本文中介绍的创建资源栈是以 python 调用 ROS 开放 API 实现的,所以首先需要在 Master 上安装 ROS SDK,具体的安装过程可参考阿里云资源编排服务Python SDK使用入门

对应用的部署是通过 Ansible 完成的,所以在 Master 上要安装 Ansible。为了避免不必要的麻烦,建议安装 Ansible 的最新版本,具体安装过程可参考 Ansible 安装文档

基于 ROS 创建资源栈,搭建资源环境

在安装完开发环境后,将开始基于 ROS 搭建资源环境。首先根据需求,定义所要创建资源的模板,并将模板添加到 python 文件中,然后 python 以该模板作为参数调用 ROS API,进而实现对资源的创建,具体的调用方式可参考阿里云资源编排服务Python SDK使用入门或者本文第三部分的示例应用。

创建 Inventory,获取 Playbook

根据 Ansible 的运行机制,在搭建好资源环境后,首先需要根据资源栈的创建结果,再次调用 ROS API 以获取云主机资源的登录信息,如:主机 IP、主机登录密码等。然后利用主机信息生成 Inventory 文件,以作为 Ansible 管理主机的清单。在 Inventory 文件中,你可以定义登录云主机的方式,如下是一个示例 Inventory 文件:

[webservers]
192.168.xx.xx ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=abc123
192.168.xx.xx ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=abc123

文件中定义了远程主机 webservers,并指明了该主机组下有两台云主机的登录地址、登录协议(默认是 SSH )、登录端口、登录用户名和密码。

最后,根据所要部署的应用,可在 Ansible 社区中查询并获取应用相关的 playbook。当然,除了这种获取方式,您还可以根据应用部署的过程,依据 YMAL 语法和 Jinja2 模板语言编写自己的playbook。

执行 Playbook,快速部署应用

Ansible 在运行 Playbook 时需要指定执行文件,执行文件可根据 Inventory 文件和 Playbook 进行编写。执行文件中需要指定所要运行的 Playbook 名称和远程主机或者远程主机组名,如下是一个执行文件 example.yml,文件中显示了对远程组webservers 执行名称为 example 的 Playbook:

---
- hosts: webservers
    roles: 
      - Example

执行文件编写成功后,运行以下命令即可完成对 Playbook 的执行:

ansible-playbook example.yml  

基于 ROS 和 Ansible 快速搭建 Redis 集群

为了更好的说明基于 ROS 和 Ansible 快速交付应用的过程,本文将以搭建 Redis 集群作为展示示例。

目前我已经构建好了我的 VPC 环境,我的 Master 上已经安装了 ROS SDK 和 Ansible,下面我将展示基于 ROS SDK 和 Ansible 快速搭建一主(Master)两备(Slave) Redis 集群的详细过程。

为了提高 Redis 集群的高可用性,在搭建 Redis 集群时为其部署了高可用性解决方案 Sentinel,以帮助 Redis 集群实现自动化的主备切换。

构建资源环境

首先定义资源栈模板。由于我已经构建好了我的 VPC 环境和控制节点 Master,所以模板中只需要定义构建三台云主机 ECS 资源并与已有的 VPC 环境相关联即可。为了方便起见,我在模板中使用资源 "Type": "ALIYUN::ECS::InstanceGroup" 定义 ECS 资源。定义资源栈的模板可详见附件中的 python 文件 create_instancegroup_template.py。

模板定义成功后,编辑 python 代码,以模板作为参数,调用 ROS API 即可实现对资源环境的搭建,如下是调用 ROS API 的 python 文件 create_stack_instancegroup.py:

# invoke CreateStackRequest to create InstanceGroup stack

from aliyunsdkcore.client import AcsClient
from aliyunsdkros.request.v20150901 import CreateStacksRequest
import create_instancegroup_template
import json

# define stack creation timeout(minutes)
create_timeout = 60

# define func to create stack
def create_stack(stack_name, ak_id, ak_secret, region_id):
    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})

    template = create_instancegroup_template.generate_template(io_optimized='optimized', network_type='vpc', image_id='centos6u5_64_40G_cloudinit_20160427.raw', security_group_id='sg-94qyqvpvj', instance_password='********', instance_min_amount=3, system_disk_category='cloud_ssd', instance_max_amount=3, vswitch_id='vsw-sm9i9vhin', vpc_id='vpc-a6al8acn4', instance_type='ecs.n1.small')

    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]:
        parameters = json.loads(response[-1])
        print('Create stack succeccfully!!!')
        return parameters
    else:
        print('Unexpected errors: status=%d, error=%s' % (response[0], response[-1]))
        return None

调用成功后,登录 ROS 控制台即可看到正在创建的资源栈。

创建 Inventory,获取 Playbook

接下来创建 Inventory 文件。为了省去手动编写 Inventory 文件的麻烦,本文使用 python 程序自动生成。首先在栈资源创建成功后,再次调用 ROS API 获取资源 ECS 的登录信息,由于资源栈的创建时间一般需要2~5分钟(视具体情况而定),所以在程序中需设置一定的等待时间,如下所示:

# define func to get host ip
def get_host_ips(stack, ak_id, ak_secret, region_id):
    # get host ip
    print('Start to get host ips...')

    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
            private_ips = resources['Outputs'][0]['OutputValue']
            print('Getting host ips finished. ips: ', private_ips)
            return private_ips
        else:
            print('Unexpected errors: status=%d, error=%s' % (response[0], response[-1]))
            return None
    print('Getting host ips timeout.')
    return None

获取云主机 IP 后,即可开始生成 Inventory 文件,由于远程主机的登录密码在创建资源栈时指定的,所以此处可直接引用,如下所示:

# define func to create inventory
def edit_hosts(remote_ips, remote_ports, remote_users, remote_pass, is_sentinel):
if remote_ips is None or 0>=len(remote_ips):
    print('Error! Remote ips is empty!')
    return
else:
    if remote_ports is None or len(remote_ips)!=len(remote_ports):
        print('Error! Remote ports is empty!')

    if remote_users is None or len(remote_ips)!=len(remote_users):
        print('Error! Remote users is empty!')

    if remote_pass is None or len(remote_ips)!=len(remote_pass):
        print('Error! Remote pass is empty!')

    host_str = ' ansible_ssh_port=%s ansible_ssh_user=%s ansible_ssh_pass=%s\n'
    file = open(hosts_dir + '/' + hosts_file, 'wb')
    file.write( '[%s]\n' % host_master )
    file.write( ('%s'+host_str) % (remote_ips[0], remote_ports[0], remote_users[0], remote_pass[0]) )
    if len(remote_ips)>1:
        file.write( '\n[%s]\n' % host_slave )
        for index in range(1,len(remote_ips)):
            file.write( ('%s'+host_str) % (remote_ips[index], remote_ports[index], remote_users[index], remote_pass[index]) )
    if is_sentinel:
        file.write( '\n[%s]\n' % host_sentinel )
        for index2 in range(0,len(remote_ips)):
            file.write( ('%s redis_sentinel=True'+host_str) % (remote_ips[index2], remote_ports[index2], remote_users[index2], remote_pass[index2]) )
    file.close()
print 'End'

文件生成后,开始获取搭建 Redis 集群的 playbook,本文使用的是 DavidWittman 编写的 playbook:DavidWittman.redis,直接调用 ansible 的命令行工具 ansible-galaxy 即可将 playbook 直接下载到 Ansible 的 roles 目录下(当然也可以使用其他下载方式,但下载后要将其放在 roles 目录下)。由于命令 ansible-galaxy 使用的是 https 通信协议,所以在调用该命令前应该确认当前主机以安装 openssl,如下所示:

# Install openssl before execute ansible-galaxy
print('Install openssl ...')
subprocess.call('yum install openssl -y', shell=True)

# install playbook
print('Download playbook %s...' % pb_name)
subprocess.call('ansible-galaxy install ' + pb_name + ' -vvv', shell=True)

搭建 Redis 集群的 playbook DavidWittman.redis 获取成功后,由于 DavidWittman.redis 编写完成时默认只部署了 Sentinel,没有实现 Redis 集群的主备配置,所以在运行 DavidWittman.redis 前,需要对 DavidWittman.redis 的 /tasks/main.yml 进行修改,使其完成分布式 Redis 集群的搭建,如下所示:


# define func to mod playbook
def mod_playbook():
    file = open(ansible_dir + '/roles/' + pb_name + '/tasks/main.yml', 'rb+')
    lines=file.readlines()
    for row in range(0, len(lines)):
        if lines[row].find('when: not redis_sentinel')>=0:
           lines[row] = '#' + lines[row]
           break
    file = open(ansible_dir + '/roles/' + pb_name + '/tasks/main.yml', 'wb+')
    file.writelines(lines)

执行 Playbook,快速部署应用

在执行 playbook 前需要编写 playbook 的执行文件。和 Inventory 文件一样,执行文件可根据下载的 playbook 利用程序自动生成,如下所示:

# define func to create playbook init config
def create_pb_init(host_ip, has_slaves, is_sentinel):
# config master
file_pb = open(pb_file_dir + '/' + pb_file_name, 'wb')
file_pb.write(redis_playbook_template.create_playbook(template='master', host_master_name=host_master, host_slave_name=host_slave, host_sentinel_name=host_sentinel, playbook_name=pb_name, master_ip=host_ip, master_port='6379', master_name='master01'))
file_pb.close()

# config slaves
if has_slaves:
    file_pb = open(pb_file_dir + '/' + pb_file_name, 'ab')
    file_pb.write(redis_playbook_template.create_playbook(template='slaves', host_master_name=host_master, host_slave_name=host_slave, host_sentinel_name=host_sentinel, playbook_name=pb_name, master_ip=host_ip, master_port='6379', master_name='master01'))
    file_pb.close()

# config sentinel
if is_sentinel:
    file_pb = open(pb_file_dir + '/' + pb_file_name, 'ab')
    file_pb.write(redis_playbook_template.create_playbook(template='sentinel', host_master_name=host_master, host_slave_name=host_slave, host_sentinel_name=host_sentinel, playbook_name=pb_name, master_ip=host_ip, master_port='6379', master_name='master01'))
    file_pb.close()

程序中使用到的生成执行文件的模板文件redis_playbook_template.py 可详见附件。

接下来即可通过运行 ansible 的命令 ansible-playbook 执行 playbook ,从而完成 Redis 集群的搭建,如下所示:

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

创建 Inventory、获取 Playbook、生成执行文件以及执行 Playbook 的代码可详见附件中的 execute_redis_playbook.py 文件。

python 代码执行的 main.py 如下所示:

import execute_redis_playbook
import time
# invoke ros api params
ak_id=''
ak_secret=''
instance_password=''
region_id='cn-shenzhen'
is_sentinel = True

# define func main
def main():
    start_time = time.time()
    execute_redis_playbook.execute(ak_id, ak_secret, region_id, instance_password, is_sentinel)
    end_time = time.time()
    print end_time-start_time
if __name__=='__main__':
    main()

在运行 main.py 前,需要指定账户的 AccessKeys 信息、云主机密码以及可用区。

以上便是基于 ROS 和 Ansible 搭建 Redis 集群的全部过程,示例中 Redis 集群中节点数量是三个,当然也可以通过修改云主机 ECS 的数量,实现对单个节点或更多节点的 Redis 集群的搭建。本示例 Redis 集群搭建成功后的资源拓扑图如下所示:
redis

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

附件下载:https://developer.aliyun.com/topic/download?id=282

相关文章
基于资源编排和 Ansible 在经典网络下快速交付应用
本文是基于资源编排和 Ansible 在 VPC 下快速交付应用的姊妹篇,即在经典网络下基于资源编排和 Ansible 实现对应用的快速交付。 在经典网络环境和 VPC 环境下交付应用的最大区别在于经典网络环境不需要 VPC、VSwitch等其他相关资源的支持,只需要 ECS 和 EIP 资源即可
4903 0
基于资源编排一键交付应用之基于WaitCondition的通知机制
随着各类应用的不断发展,许多应用开发人员对应用部署的便捷性和应用运行的稳定性都提出了很高的要求,从这个意义上来讲,应用的一键交付以及对应用做负载均衡将会是一个不错的解决方案。对开发人员而言,在交付应用时如何才能保证对应用所做的负载均衡是成功的呢?此时,有效控制应用的部署过程并且感知应用的部署结果,将
3897 0
基于资源编排一键交付连接RDS的应用
众所周知,许多 Web 应用都会涉及对数据库的访问,但出于对数据的保护,通常我们在构建应用时会将应用本身和其对应的数据库分别部署在不同的机器上,以实现数据与应用相隔离。同时,为了降低应用构建的复杂度,阿里云提供了稳定可靠、可弹性伸缩的在线数据库服务 RDS,实现了对数据库的快速部署,从而使得对应用的
3139 0
基于资源编排一键交付应用
资源编排可通过资源编排模板定义您需要创建的阿里云资源的组合,并依据您的配置来完成对资源的配置和一键销毁,快速方便的构建您的应用。本文将引导您如何基于资源编排服务快速构建一个应用。首先引入三个概念:Meta-Data、Cloud-Init 和 User-Data。 Meta-DataMeta-D
7534 0
使用资源编排ROS一键批量开通阿里云产品
## 背景 如果你使用过阿里云的云产品/服务,你会发现其中有不少需要手动点击“开通”。比如初次使用 SLS 日志服务时,就会进入下面的界面: ![sls-enable-service.jpg](https://ata2-img.oss-cn-zhangjiakou.aliyuncs.com/561d3fc5d9805e79a62a41a9094019c3.jpg) 作为个人用户,以手
1508 0
阿里云资源编排之函数计算
资源编排服务(Resource Orchestration Service, 简称ROS)是阿里云提供的一项简化云计算资源管理的服务。您可以遵循ROS定义的模板规范编写资源栈模板,在模板中定义所需的云计算资源(例如ECS实例、RDS数据库实例)、资源间的依赖关系等。本文将为您详细介绍阿里云资源编排服务的函数计算相关功能。
897 0
阿里云资源编排之函数计算
资源编排服务(Resource Orchestration Service, 简称ROS)是阿里云提供的一项简化云计算资源管理的服务。您可以遵循ROS定义的模板规范编写资源栈模板,在模板中定义所需的云计算资源(例如ECS实例、RDS数据库实例)、资源间的依赖关系等。ROS的编排引擎将根据模板自动完成所有资源的创建和配置,实现自动化部署及运维。 ROS资源编排接入了大量的阿里云资源,目前涉
1146 0
阿里云资源编排之异步通知
资源编排服务(Resource Orchestration Service, 简称ROS)是阿里云提供的一项简化云计算资源管理的服务。您可以遵循ROS定义的模板规范编写资源栈模板,在模板中定义所需的云计算资源(例如ECS实例、RDS数据库实例)、资源间的依赖关系等。ROS的编排引擎将根据模板自动完成所有资源的创建和配置,实现自动化部署及运维。 ROS资源编排接入了大量的阿里云资源,目前涉
632 0
阿里云资源编排之函数计算
本文介绍阿里云资源编排服务(ROS)(下面简称ROS)函数计算相关功能,涉及如下资源类型: ALIYUN::FC::Service  创建服务 ALIYUN::FC::Function  创建函数 ALIYUN::FC::FunctionInvoker 主动执行函数 ALIYUN::FC::Trigger  创建触发器,触发执行函数 通过使
1207 0
使用阿里云资源编排部署SAP单节点HANA
本文使用[阿里云资源编排服务(ROS)](https://www.aliyun.com/product/ros/)(下面简称ROS),在控制台中快速部署和安装SAP单节点HANA。 相较于原SAP HANA部署流程([SAP HANA 部署指南](SAP HANA 部署指南)),使用ROS部署只需要三步即可完成。不仅可以轻松创建SAP HANA需要的云资源,并且支持自动化部署和配置,简化了交
2660 0
+关注
箫竹Aaron
阿里云高级开发工程师,主要负责开源DevOps工具(Terraform,Ansible,Cloud Foundry)与阿里云的集成, 专注通过主流开源高效的自动化工具提高云上运维/开发的便利性。
文章
问答
文章排行榜
最热
最新
相关电子书
更多
ANSIBLE在生产环境中的实践
立即下载
Terraform - 管理云资源的正确姿势
立即下载
Terraform-管理云资源的正确姿势
立即下载