弹性伸缩(Elastic Scaling Service, ESS)根据用户的业务需求和策略,自动调整对弹性计算资源的管理,使得在满足业务需求高峰增长时无缝地增加 ECS 实例,并在业务需求下降时自动减少 ECS 实例以节约成本。
随着业务量和功能的不断增加,越来越多的用户开始选择 ESS 来实现对业务的弹性支撑服务。然而,ESS 只能实现对 ECS 实例的自动调整,并不能让业务随着 ECS 实例的伸缩进行自动化调整。
针对以上的问题,开源工具 Packer 和 Terraform 提出了相应的解决方案。本文将向您展示如何利用 Packer 和 Terraform 实现对具体业务的弹性伸缩。方便起见,本文将以弹性伸缩 Jenkins 服务为例进行详细说明。
ESS 的局限性
ESS 根据用户业务的需求和策略,自动的调整 ECS 实例的数量,以实现业务的有效运行和对成本的有效控制。
然而,ESS 只解决了业务所在机器 ECS 的弹性伸缩问题,对具体业务的弹性伸缩却无法满足。正如上图所示,随着 Jenkins 业务的不断调整,ESS 根据 ECS 实例配置和相应的伸缩规则对 ECS 进行弹性伸缩,然后利用 Jenkins 部署脚本或者其他工具在扩展后的 ECS 上手动部署 Jenkins 服务,以达到扩展 Jenkins 服务的目的。如此一来,业务的管理和运维成本势必随着业务量的加大而不断增加。
Packer & Terraform 让 ESS 更灵活
面对如上的尴尬的问题,我们引入了开源工具 Packer 和 Terraform:
- Packer
A free and open source tool for creating golden images for multiple platforms from a single source configuration.
Alibaba/packer-provider : https://github.com/alibaba/packer-provider
- Terraform
A open source tool for building, changing, and versioning infrastructure safely and efficiently.
Alibaba/terraform-provider : https://github.com/alibaba/terraform-provider
首先,基于 Packer 快速定制 Jenkins 服务的镜像,接着将定制化的镜像作为 ESS 配置 ECS 实例配置的参数,最后基于 Terraform 和 ESS 的伸缩配置及伸缩规则实现面向 Jenkins 服务的ESS。
Packer 定制 Jenkins 服务镜像
如上图所示,首先利用 ECS Image 和 Jenkins 部署脚本基于 Packer 快速定制安装有 Jenkins 服务的镜像,此次的定制需要借助于 Packer 和 Alibaba/packer-provider,所以在定制前需要在开发环境中安装 Packer 和 面向 Alicloud 的 packer-provider。下面是定制镜像的详细步骤:
- 安装 Packer
访问 Packer 下载页面 下载 MAC v1.0.0 版(可根据本地的开发环境自行选择版本)的 Packer 安装包,然后在将其放置在本地的 /bin 目录下(由于 Packer 和 Terraform 都是 Go 语言编写的,方便起见,将它们都存放在 Go 工作目录的 bin 目录下),解压后设置环境变量即完成安装。
cd $<GOPATH>/bin
wget https://releases.hashicorp.com/packer/1.0.0/packer_1.0.0_darwin_amd64.zip
unzip packer_1.0.0_darwin_amd64.zip
# 验证是否安装成功
packer -version
- 安装 packer-provider
为了安装方便,避免源码安装,目前已经提供了三种操作系统的 packer-provider 安装包 Mac 64-bit,Linux 64-bit 以及 Windows 64-bit,下载即可完成安装。
cd $<GOPATH>/bin
wget https://github.com/alibaba/packer-provider/releases/download/V1.1/packer-builder-alicloud-ecs_darwin-amd64.tgz
tar -xzf packer-builder-alicloud-ecs_darwin-amd64.tgz
设置环境变量
运行 Packer 前需要设置环境变量 AKSet environment AK
export ALICLOUD_ACCESS_KEY="access key value"
export ALICLOUD_SECRET_KEY="secret key value"- 编写 Packer Jenkins 模板,自定义 Jenkins 镜像的属性
packer-provider 已经提供了定制 Jenkins 镜像的模板,下图是模板的一部分,详见附件。
{
"variables": {
"access_key": "{{env `ALICLOUD_ACCESS_KEY`}}",
"secret_key": "{{env `ALICLOUD_SECRET_KEY`}}"
},
"builders": [{
"type":"alicloud-ecs",
"access_key":"{{user `access_key`}}",
"secret_key":"{{user `secret_key`}}",
"region":"cn-beijing",
"image_name":"packer_jenkins",
"source_image":"ubuntu_14_0405_64_40G_base_20170222.vhd",
"ssh_username":"root",
"instance_type":"ecs.n1.medium",
"io_optimized":"true",
"image_force_delete":"true",
"ssh_password":"Test12345"
}],
"provisioners": [{
"type": "file",
"source": "examples/alicloud/jenkins/jenkins.sh",
"destination": "/root/"
},{
"type": "shell",
"inline": [
"cd /root/",
"chmod 755 jenkins.sh",
"./jenkins.sh"
]
}]
}
下载模板,编辑模板文件 alicloud-template/packer/examples/alicloud/jenkins/alicloud.json,可自定义镜像属性,如修改镜像名称 image_name
,源镜像 source_image
,镜像 SSH 登录密码 ssh_password
等.
运行 Jenkins 模板,定制 Jenkins 镜像
Execute packer build
cd alicloud-template/packer
packer build examples/alicloud/jenkins/alicloud.json整个镜像定制过程大约持续10分钟,定制结束后,packer-provder将返回 imageId 以及其他镜像信息。
Terraform 搭建 Jenkins ESS
1. 本地安装 Terraform 和 terraform-provider
利用定制化的镜像,基于 terraform-provider 即可实现对 Jenkins ESS 的快速搭建。首先在开发环境中安装 Terraform 和面向 Alicloud 的 terraform-provider,它们也是由 Go 语言编写的。
- 安装 Terraform
和 Packer 类似,访问 Terraform 下载页面 下载 MAC v1.0.0 版(可根据本地的开发环境自行选择版本)的 Packer 安装包,然后在将其放置在本地的 /bin 目录下(由于 Packer 和 Terraform 都是 Go 语言编写的,方便起见,将它们都存放在 Go 工作目录的 bin 目录下),解压后设置环境变量即完成安装。
cd $<GOPATH>/bin
wget https://releases.hashicorp.com/terraform/0.9.2/terraform_0.9.2_darwin_amd64.zip
unzip terraform_0.9.2_darwin_amd64.zip
# 验证是否安装成功
terraform -version
- 安装 terraform-provider
和 packer-provider 类似,terraform-provider 也提供了三种操作系统的安装包Mac 64-bit,Linux 64-bit 以及 Windows 64-bit ,下载即可完成安装。
cd $<GOPATH>/bin
wget https://github.com/alibaba/terraform-provider/releases/download/V1.0.5/terraform-provider-alicloud_darwin-amd64.tgz
tar -xzf terraform-provider-alicloud_darwin-amd64.tgz
2. 编写搭建 Jenkins ESS 的 Terraform 模板
terraform-provider 提供了快速搭建 ESS 的模板,在这基础上,我们利用已经定制化的镜像只需要修改 ESS 模板中的少量配置,即可快速搭建面向 Jenkins 服务的 ESS,如下是模板中的文件 main.tf
,模板详见附件。
data "alicloud_images" "ecs_image" {
most_recent = true
name_regex = "^centos_6\\w{1,5}[64].*"
}
resource "alicloud_security_group" "sg" {
name = "${var.security_group_name}"
description = "tf-sg"
}
resource "alicloud_security_group_rule" "ssh-in" {
type = "ingress"
ip_protocol = "tcp"
nic_type = "internet"
policy = "accept"
port_range = "22/22"
priority = 1
security_group_id = "${alicloud_security_group.sg.id}"
cidr_ip = "0.0.0.0/0"
}
resource "alicloud_ess_scaling_group" "scaling" {
min_size = "${var.scaling_min_size}"
max_size = "${var.scaling_max_size}"
scaling_group_name = "tf-scaling"
removal_policies = "${var.removal_policies}"
}
resource "alicloud_ess_scaling_configuration" "config" {
scaling_group_id = "${alicloud_ess_scaling_group.scaling.id}"
enable = "${var.enable}"
image_id = "${data.alicloud_images.ecs_image.images.0.id}"
instance_type = "${var.ecs_instance_type}"
io_optimized = "optimized"
security_group_id = "${alicloud_security_group.sg.id}"
}
resource "alicloud_ess_scaling_rule" "rule" {
scaling_group_id = "${alicloud_ess_scaling_group.scaling.id}"
adjustment_type = "TotalCapacity"
adjustment_value = "${var.rule_adjust_size}"
cooldown = 60
}
resource "alicloud_ess_schedule" "run" {
scheduled_action = "${alicloud_ess_scaling_rule.rule.ari}"
launch_time = "${var.schedule_launch_time}"
scheduled_task_name = "tf-run"
}
根据新定制的镜像修改 Terraform 模板文件,具体操作步骤如下:
- 修改 ESS 模板 main.tf
编辑文件 alicloud-template/terraform/examples/alicloud-ess-schedule/main.tf,将资源alicloud_images
的name_regex
参数设置为定制化镜像的名称,即上文中提到的image_name
,接着,由于 Jenkins 服务需要开通 8080 端口,所以需要设置 ECS 实例的安全组规则,为了方便起见,只需要将资源alicloud_security_group_rule
的参数port_range
修改为 "8080/8080" 即可,除此之外,您还可以设置伸缩组的其他属性,如伸缩组名称scaling_group_name
,ECS 实例类型instance_type
等。 - 修改 ESS 模板变量 variable.tf
为了可以尽快的看到伸缩效果,我们可以设置伸缩定时任务的执行时间为未来 2 分钟。编辑文件 terraform/examples/alicloud-ess-schedule/variable.tf,修改变量schedule_launch_time
,此变量按照ISO8601标准表示,并使用UTC时间,格式为:YYYY-MM-DDThh:mmZ,由于北京时区是东八区,领先 UTC 八个小时,因此可根据未来本地未来两分钟的时间,利用公式:UTC = 本地时间 - 8 来进行设置。除此之外,您还可以设置最大最小伸缩实例的数量scaling_max_size
和scaling_min_size
,一次伸缩实例的数量rule_adjust_size
等。
3. 搭建 Jenkins ESS
编写完 ESS 的 Terraform 模板后,即可利用 terrafrom 实现对 Jenkins ESS 的快速搭建:
# execute terraform template
cd alicloud-template/terraform/examples/alicloud-ess-schedule
# preview resource
terraform plan
# create resource
terraform apply
整个搭建过程不超过 30 秒,搭建结束后,等待 ESS 定时任务的自动执行,执行结束后 ESS 将会扩展出指定数量的安装有 Jenkins 服务的 ECS。登录 ESS 控制台 即可查看 ESS 的详细信息。
4. 访问 Jenkins 服务
登录 ESS 控制台后,在相应 ESS 的“ECS 实例列表”页面即可查看已经伸缩的 ECS 实例,查看实例详情即可获取 Jenkins 实例的公网 IP,在浏览器中输入 <public_ip>:8080/jenkins
即可访问 Jenkins 服务。
写在最后
随着用户的业务需求和策略的不断变化,ESS 完美的解决了运行业务实例的自动伸缩,但却无法解决对业务的自动伸缩。Packer 和 Terraform 的出现,结合 ESS 在解决实例自动伸缩的同时,有效地实现了用户业务的自动伸缩,有效降低了用户对业务的管理和运维成本,实现了整个业务流程的代码化。