简单高效的云服务器单元化扩容方案

自从ECS这类云服务器出现以来,越来越多的公司把自己的网站、应用和IT系统放到了云上。究其原因,IDC等基础设施的巨大成本节省和部署门槛降低是很重要的一个原因。除此以外,云服务按需获取的特性也带来了更多的运维创新的可能性。

比如应用的扩容。传统IDC托管环境下,我们总是要为未来可能的扩容需求而预留足够的服务器资源,既不能有太多资源浪费,还需要考虑未来扩容的需要,容量规划就成了一个很重要又困难的工作。而ECS这类云服务器,我们基本认为是可以随时按需获取的,既方便快捷,又节约人力、物理成本。

虽然云服务器提供了按需获取资源的能力,但是如何把这种能力应用到我们自己的业务上并不是那么直观和简单的事情。还是以应用扩容这个需求来说,一种可能的做法是,当需要扩容时,运维人员手动的通过WEB管理界面去下单购买新的云服务器,然后对系统进行配置,安装软件,最后上线。另一种做法可以是通过自动化运维程序,自动创建服务器,自动配置,自动安装软件,自动上线。两种做法在人力成本和可靠性上有巨大的差别。第一种方式需要运维人员大量的重复性劳动,而且容易出错,第二种方式需要运维人员有很强的代码能力,把云服务和自己的应用进行集成。总结下来,就扩容这个需求,如何才能既简单又高效的完成呢,我们先梳理一下要求,大概如下:

  1. 服务器按需获取,不使用不付费
  2. 全部自动化,运维人员只需要简单的操作即可达到扩容目的,包括服务器获取、系统配置
  3. 不需要复杂的集成开发工作,所使用的工具有专业团队支持,开箱即用
  4. 响应快速,整个扩容过程,能够在分钟级别完成
  5. 每次扩容的容量可以任意定义,即支持批量扩容
  6. 支持逆向操作,即当业务流量发生减少,可以取消之前的扩容

这么看起来,扩容这件事并不是那么简单。即使开发能力很强的运维团队,如果想做到以上全部,依然需要做大量的开发工作去处理扩容逻辑和可靠性。同时,还要去处理云产品的OpenAPI调用过程的各种细节,像重试、幂等调用、边界条件处理等等。

阿里云的资源编排服务(ROS)是一款简化自动化运维的服务,支持用户通过模板描述基础设施。所以,ROS已经提供了资源的创建和配置功能,而且帮我们屏蔽了底层资源操作的复杂性,我们只需要编写模板文件即可。在应用扩容这个场景下,ROS依然可以帮我们满足上面所列的七点要求。

下面我们就来介绍一下,如何通过ROS来做应用的扩容。关于ROS的介绍和使用入门请参考:

首先,假设我们运维的是一个B2C的电子商务网站,日常情况下,平均日访问量200万PV。考虑到电商网站的特性,有大量耗时较长的事务需要处理,日常需要3台云服务器来支撑整个网站的运行。每年双十一前后,网站会配合各大电商平台进行促销活动,促销期间,日均访问量最高会达到日常的5到10倍。

为了应对临时性的扩容需求,网站从架构和部署方面已经做了针对性设计。整个网站的应用可以部署到一*立的云服务器上,并且做了无状态设计,支持水平扩展。前端通过SLB做流量负载均衡。所有的数据存储在一个高规格的RDS实例中。整个架构如下:

简单高效的云服务器单元化扩容方案

为了应对促销季5到10倍的流量增长,我们的扩容思路如下:

  • 将整个网站应用制作成一个服务器镜像,方便通过镜像进行应用部署
  • 通过ROS的编排模板定义扩容服务器的配置,包括数量、使用的镜像、规格、SLB/RDS的依赖关系等
  • 把5台机器定义为一个扩容单元,扩容单元通过ROS创建,随着流量增加,每次扩容增加一个扩容单元
  • 当流量回落后,以扩容单元为单位缩小容量,直至日常状态

扩容过程如下图所示:

简单高效的云服务器单元化扩容方案

通过ROS完成扩容只需要把对应的扩容单元的模板提交到ROS服务即可。详细的模板如下:

{
    "ROSTemplateFormatVersion": "2015-09-01",
    "Description": "根据指定的ECS实例ID,克隆出指定数量的相同配置的机器,并挂载到指定SLB。使用本模板创建的资源栈为一个扩容单元。",
    "Parameters": {
        "SourceInstanceId": {
            "Description": "指定来源ECS实例ID,所克隆机器会完全复制次实例。",
            "Type": "String"
        },
        "ImageId": {
            "Description": "指定创建机器使用的ImageId。",
            "Type": "String"
        },
        "SLBId": {
            "Description": "机器创建成功后被自动挂载到指定的SLB。",
            "Type": "String"
        },
        "InstanceName": {
            "Description": "[2, 128] 中英文字符, '_' or '.', '-' ",
            "Type": "String",
            "MaxLength": 128,
            "MinLength": 2,
            "ConstraintDescription": "8-30个字符,可以包含大、小写字母和特殊字符",
            "Default": "ecsInstance"
        },
        "MaxAmount": {
            "Description": "创建ECS实例数量的上限,并且要大于MinAmount。",
            "MaxValue": 100,
            "MinValue": 1,
            "ConstraintDescription": "[1, 100]之间的整数",
            "Type": "Number"
        },
        "MinAmount": {
            "Default": 1,
            "Description": "创建ECS实例个数的下限,并且要小于MaxAmount",
            "MaxValue": 100,
            "MinValue": 1,
            "ConstraintDescription": "[1, 100]之间的整数",
            "Type": "Number"
        },
        "Password": {
            "Description": "ECS登录密码.",
            "MaxLength": 30,
            "MinLength": 8,
            "NoEcho": true,
            "ConstraintDescription": "8-30个字符,可以包含大、小写字母和特殊字符",
            "Type": "String"
        }
    },
    "Resources": {
        "ecsInstanceGroup": {
            "Type": "ALIYUN::ECS::InstanceGroupClone",
            "Properties": {
                "SourceInstanceId": {
                    "Ref": "SourceInstanceId"
                },
                "ImageId": {
                    "Ref": "ImageId"
                },
                "LoadBalancerIdToAttach": {
                    "Ref": "SLBId"
                },
                "InstanceName": {
                    "Ref": "InstanceName"
                },
                "MaxAmount": {
                    "Ref": "MaxAmount"
                },
                "MinAmount": {
                    "Ref": "MinAmount"
                },
                "Password": {
                    "Ref": "Password"
                }
            }
        }
    },
    "Outputs": {
        "InstanceIds": {
            "Description": "输出新创建的ECS实例的ID列表",
            "Value": {
                "Fn::GetAtt": ["ecsInstanceGroup", "InstanceIds"]
            }
        },
        "PublicIps": {
            "Description": "输出新创建的ECS实例的IP地址列表",
            "Value": {
                "Fn::GetAtt": ["ecsInstanceGroup", "PublicIps"]
            }
        }
    }
}

ROS控制台已经提供了一个可以快速使用的样例模板,您只要根据自己的需要简单修改、配置即可。扩容样例

上一篇:Kubeflow Pipeline — 基于Kubernetes 的机器学习工作流


下一篇:构建Tensorflow RDMA的Docker镜像