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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
资源编排,不限时长
简介: 阿里云资源编排服务(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

相关实践学习
2分钟自动化部署人生模拟器
本场景将带你借助云效流水线Flow实现人生模拟器小游戏的自动化部署
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1月前
|
运维 应用服务中间件 持续交付
自动化运维的利器:Ansible实战应用
【9月更文挑战第33天】本文将带你深入理解Ansible,一个强大的自动化运维工具。我们将从基础概念开始,逐步探索其配置管理、任务调度等功能,并通过实际案例演示其在自动化部署和批量操作中的应用。文章旨在通过浅显易懂的语言和实例,为读者揭开Ansible的神秘面纱,展示其在简化运维工作中的强大能力。
164 64
|
5天前
|
运维 应用服务中间件 Linux
自动化运维的利器:Ansible在配置管理中的应用
【10月更文挑战第39天】本文旨在通过深入浅出的方式,向读者展示如何利用Ansible这一强大的自动化工具来优化日常的运维工作。我们将从基础概念讲起,逐步深入到实战操作,不仅涵盖Ansible的核心功能,还会分享一些高级技巧和最佳实践。无论你是初学者还是有经验的运维人员,这篇文章都会为你提供有价值的信息,帮助你提升工作效率。
|
2月前
|
运维 安全 应用服务中间件
自动化运维的利剑:Ansible实战应用
【9月更文挑战第24天】在现代IT基础设施的快速迭代与扩展中,自动化运维成为提升效率、保障稳定性的关键。本文将深入探讨Ansible这一流行的自动化工具,通过实际案例分析其如何简化日常运维任务,优化工作流程,并提高系统的可靠性和安全性。我们将从Ansible的基础概念入手,逐步深入到高级应用技巧,旨在为读者提供一套完整的Ansible应用解决方案。
|
8天前
|
运维 Ubuntu 应用服务中间件
自动化运维工具Ansible的实战应用
【10月更文挑战第36天】在现代IT基础设施管理中,自动化运维已成为提升效率、减少人为错误的关键手段。本文通过介绍Ansible这一流行的自动化工具,旨在揭示其在简化日常运维任务中的实际应用价值。文章将围绕Ansible的核心概念、安装配置以及具体使用案例展开,帮助读者构建起自动化运维的初步认识,并激发对更深入内容的学习兴趣。
29 4
|
6天前
|
运维 安全 应用服务中间件
自动化运维的利剑:Ansible在配置管理中的应用
【10月更文挑战第37天】本文将深入探讨如何利用Ansible简化和自动化复杂的IT基础设施管理任务。我们将通过实际案例,展示如何用Ansible编写可重用的配置代码,以及这些代码如何帮助运维团队提高效率和减少人为错误。文章还将讨论如何构建Ansible playbook来自动部署应用、管理系统更新和执行常规维护任务。准备好深入了解这个强大的工具,让你的运维工作更加轻松吧!
21 2
|
1月前
|
运维 关系型数据库 MySQL
自动化运维工具Ansible的实战应用
【10月更文挑战第9天】在现代IT运维领域,效率和可靠性是衡量一个系统是否健康的重要指标。自动化运维工具Ansible因其简洁、易用的特性,成为了众多企业和开发者的首选。本文将通过实际案例,展示如何利用Ansible进行日常的运维任务,包括配置管理、软件部署以及批量操作等,帮助读者深入理解Ansible的应用场景及其带来的效益。
|
2月前
|
运维 应用服务中间件 网络安全
自动化运维之路:Ansible在配置管理中的应用
【9月更文挑战第15天】本文深入探讨了自动化运维工具Ansible的基本原理和实际应用,通过实例演示如何利用Ansible进行高效的配置管理和批量部署。文章不仅涵盖了Ansible的安装、配置以及基础使用,还详细介绍了如何编写有效的Playbook来自动化日常任务,并讨论了Ansible的最佳实践和常见问题的解决策略,为读者提供了一套完整的解决方案。
|
2月前
|
运维 应用服务中间件 Linux
自动化运维的利剑——Ansible在配置管理中的应用
【9月更文挑战第13天】 随着IT基础设施的日益复杂,手动进行系统配置和管理变得越来越低效且容易出错。Ansible,一个开源的IT自动化工具,因其简单易用和高效的特性成为运维工程师的新宠。本文将通过浅显易懂的语言和具体案例,带你了解如何利用Ansible简化日常的运维任务,实现快速、一致的配置部署与管理。
|
2月前
|
运维 监控 应用服务中间件
自动化运维的利剑:Ansible在配置管理中的应用
【9月更文挑战第11天】 当运维工作遇到瓶颈,效率和可靠性成为制约因素时,自动化工具Ansible如同一把锋利的利剑,为配置管理和批量部署带来革命性的改变。本文将深入探讨Ansible的核心功能、使用方法及其在实际运维场景中的强大作用,带领读者领略自动化运维的魅力,并分享如何通过代码示例实现高效管理。
40 1
|
2月前
|
运维 应用服务中间件 持续交付
自动化运维的利器:Ansible在配置管理中的应用
【9月更文挑战第4天】在现代企业中,随着服务器数量的增加和业务的复杂性提高,传统的手动运维方式已经无法满足快速、高效、稳定的业务需求。自动化运维应运而生,成为提升工作效率、减少人为错误的关键技术。本文将介绍Ansible这一自动化运维工具,通过实例展示其在配置管理中的应用,帮助读者理解如何借助Ansible简化日常运维工作,实现服务器的批量管理与自动化部署。
53 4

推荐镜像

更多