【Terraform实现云服务基础设施既代码(IaC)案例实战-2】:通过Terraform实施基础IaC

简介: 前言树苗科技公司业务上云2年有余,随着技术的不断发展。运维团队支持业务变更配置、开资源、删资源等过程加班到深夜一两点已是家常便饭。为了进一步提升工作效率,运维总监张三决定对当前业务交付路径进行统一梳理,借助IaC的理念和Terraform自动化工具逐步实施运维生产自动化,改善组内成员频繁加班的现状。...

1. 前言

树苗科技公司业务上云2年有余,随着技术的不断发展。运维团队支持业务变更配置、开资源、删资源等过程加班到深夜一两点已是家常便饭。为了进一步提升工作效率,运维总监张三决定对当前业务交付路径进行统一梳理,借助IaC的理念和Terraform自动化工具逐步实施运维生产自动化,改善组内成员频繁加班的现状。

期望:

  1. 能够建设生产网和测试网络的业务交付自动化

  2. 能够有一个轻量级前段给业务团队自己申请

  3. 能够有权限管理和版本控制,防止一键删资源跑路的情况

  4. 能够使用容器技术,在短时间内交付可扩容的业务脚本

2. 组织背景

image.png

树苗科技公司共有四个部门,运维部门,品种研发部门、企业财务部门和企业安全部门。

运维部门:主要负责云上资源的管理工作,支撑各部门的业务。

品种研发部门:主要负责新品种研发和产品发布上市过程。会与运维部门频繁交付。经常会申请开通测试环境,新业务建设和旧业务扩容等需求。

3. 业务痛点

  1. 重复劳动多,一百个ECS虽说有几十个规格,但是每天日常操作也受不了。

  2. 团队空间少,运维天天做控制台点点点的事情,累死累活陪着业务加班到深夜,做的都是重复的事情。下面的人流失很快。

  3. 手工操作出错,好心加细心,还免不了背锅的命运。

4. 目标

接上一回,李四在经过技术评估后,开始采用Terraform实践一套业务框架。 希望首先以品种研发部门的“紫色枫叶”项目作为试点项目。 在于部门负责人王五一番商讨后,决定先尝试做一个试点升级。

调整前工作流程:

这个流程中,王五和李四经常需要沟通清楚需求,开什么资源,什么型号,在什么网络部署。 沟通后李四需要去控制台一个个参数选出来。复杂、重复日复一日的劳动让李四非常焦虑。 主要有些时候回复邮件需要去各个控制台复制参数,VPC的,SLB的公网IP,ECS的instance ID等。经常出错。

image.png

调整后工作流程:

可以看到,李四和王五约定后,虽然还是通过邮件申请资源作为记录。但是李四已经不需要再通过控制台操作,将各类参数手动眼+手的方式回复邮件。取而代之的是准确的交付参数的复制粘贴,增加了交付效率,减少了误操作概率。

image.png

5. 调研过程

为了解决上面问题,李四花了一些时间对IaC的理念进行了调研。

DevOps有四大核心价值:文化(culture)、自动化(automation)、度量(measurement)和共享(sharing)。基础设施即代码背后的想法是,通过编写和执行代码来定义、部署、更新和销毁基础设施。这代表着一种观念上的重要转变:将运维的各个工作都视为与软件相关,甚至包括那些明显针对硬件的工作(如设置物理服务器)。实际上,DevOps的一个重要观点是,用户应该将所有事物都在代码中进行管理,包括服务器、数据库、网络、日志文件、应用程序配置、文档、自动测试、部署过程等。

image.png

但是,即便这个理念和逻辑很多人都讲的很清楚也很了解,但是如何入手,如何从0-1-100搭建自己的业务框架。 在这个【Terraform案例实战】系列中,你我将作为一个运维团队主管共同开发和构建一个基于Terraform的基础平台框架。

IaC工具分为5大类:专项脚本、配置管理工具、服务器模板工具、编排工具、服务开通工具。

代码的功能是极其强大的。通过早期投入将手动工作转化为代码,你的软件交付能力将得到显著改善。根据2016年DevOps状况报告,使用DevOps实践(例如IaC)的组织,部署频率提高了200倍,从故障中恢复的速度提高了24倍,交付周期缩短为原来的1/2555。

业务机遇上,从基础设施到过程管理再到应用管理是面向用户的整体业务闭环。 当前很多的交付都是一线团队在做定制化。 交付成本高。 API具备resourcemeta和API的所有信息,是天然devops工作台的载体。 因此,今年能够作出面向allin阿里云和非allin阿里云(多云混合、生态集成)两大方向全面发力。

IaC主要带来三个主要的价值

  1. 成本(减少)

  2. 速度(更快的执行)

  3. 风险(人为的操作错误所带来的安全隐患)

实施IaC的团队可以快速,大规模地提供稳定的环境。团队通过代码表示环境的最终期望状态,从而避免手动配置环境并强制实现一致性。使用IaC进行基础架构部署都是可重复的,可防止因配置偏差或缺少依赖性而导致的运行时问题。

DevOps团队可以与统一的实践和工具协同工作,快速,可靠,大规模地交付应用程序及其支持基础架构。

image.png

如上图所示,从传统IT到云上IT,运维模式本质上没有发生变化。研发和运维的生产关系除了对硬件的维护边界变化外并无本质差异。 但对于云上运维团队来说,不仅仅意味着业务转型,也面临从支撑团队到业务团队的转型。

image.png

在云上IT到云上Devops的进展中,云上运维团队往往规模相对固定,而业务却会快速扩张。典型的互联网企业便是如此。 在这样的矛盾和冲突下,基础设施自动化就变得势在必行。主要解决几类问题:

  1. 标准化生产过程重复性工作(诸如:开通云服务器这个动作,很多运维同学在控制台做的是相对固化的事情)

  2. 减少人为误操作的隐患(安全领域中,人的管理也是很大风险之一)

  3. 碎片化服务器和资源(临时测试,临时开通的资源忘记释放的情况经常出现)

6. 实践过程

需求分析

李四经过需求分析后,发现去年上百个工单其实都在做几件事情:

# 1. 构建基础网络架构

# 创建VPC网络和交换机。

# 2. 安全组

# 创建安全组,并将安全组作用于上一步创建的VPC中。

# 3. 负载均衡

# 创建负载均衡实例,为其分配公网IP。在本示例中,为负载均衡实例配置了从前端80端口到后端8080端口的映射,并输出公网IP用于后续测试。

# 3. 弹性伸缩

# 伸缩组:在模板中指定伸缩最小为2,最大为10,并将伸缩组与新建的负载均衡实例绑定。由于伸缩组的配置要求SLB必须有相应配置的监听器,因此模板需要同步指定了部署顺序。

# 伸缩组配置:在模板中指定ECS实例的具体配置。在初始化配置(user-data)中生成一个Hello World的网页,并在8080端口提供服务。为简化操作,本示例中会为虚拟机分配公网IP,并且设置force_delete=true用于后续删除环境。

因此,李四定义了一个业务目标:

# 【业务效果】:

# 创建成功后,会根据以下模板输出基础设施基础信息:

  1. 输出SLB的公网IP以及资源的基础配置。

  2. 输出ESS的ID及节点配置

  3. 输出SLB的ID

  4. 输出SLBlinster的ID和配置信息

  5. 输出安全组的入网策略信息

  6. 可以直接反馈给业务团队。

# 等待大约两分钟,弹性伸缩将自动创建ECS实例。

# 输入命令curl http://进行验证。

# 如果看到Hello,World,表示成功通过负载均衡实例访问ECS实例提供的网页。

# 运行terraform destroy删除测试环境。经确认后,整个部署的环境将被删除。

搭建开发环境

Terraform基础环境构建

关于Terrafrom的基础语法和使用方法参见

Terrafrom安装教程参见

安装Homebrew

brew tap hashicorp/tap

安装Terraform

brew install hashicorp/tap/terraform

升级

brew update
brew upgrade hashicorp/tap/terraform

验证安装

terraform -help
terraform -version

实施业务场景

在李四梳理的业务场景中。主要涉及到几个资源。

资源

文档

备注

alicloud_vpc

链接

alicloud_vswitch

链接

alicloud_security_group

链接

alicloud_security_group_rule

链接

alicloud_slb

链接

alicloud_slb_listener

链接

alicloud_ess_scaling_group

链接

alicloud_ess_scaling_configuration

链接

alicloud_ess_scaling_rule             链接

对于Terrafrom的provider设置可以采用声明式的写法。如:链接

但,这种写法容易让ak,sk硬编码,从安全使用和ak轮转的未来规划都不建议这种方式进行。

provider "alicloud" {
  access_key = "${var.access_key}"
  secret_key = "${var.secret_key}"
  region     = "${var.region}"
}

或者,使用CLI去设置(更推荐)链接

# 安装CLI
brew install aliyun-cli
# 配置CLI
aliyun configure --profile akProfile

Configuring profile 'akProfile' in '' authenticate mode...
Access Key Id []: AccessKey ID
Access Key Secret []: AccessKey Secret
Default Region Id []: cn-hangzhou
Default Output Format [json]: json (Only support json))
Default Language [zh|en] en:
Saving profile[akProfile] ...Done.

之后,李四在电脑上建立了一个空文件夹,命名为“tree-project”

如下图所示: 该图为执行terraform init指令之后的项目信息。

image.png

进入这个空文件夹,执行:

PC:tree-project tiankai$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/alicloud...
- Installing hashicorp/alicloud v1.140.0...
- Installed hashicorp/alicloud v1.140.0 (signed by HashiCorp)
Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

解决业务需求

需求1:构建基础网络架构

# 创建VPC网络和交换机。

通过阅读terrafrom官网,我们很容易找到对应的资源以及示范代码。 我们设置为172网段,部署在beijing区。

resource "alicloud_vpc" "vpc" {
  vpc_name       = "tf_test_foo"
  cidr_block = "172.16.0.0/12"
}

resource "alicloud_vswitch" "vsw" {
  vpc_id            = alicloud_vpc.vpc.id
  cidr_block        = "172.16.0.0/21"
  zone_id = "cn-beijing-b"
}

需求2: 设置安全组和入网策略

在设置好VPC后,李四不希望任何人都能够访问企业的业务网络。 处于减少被攻击面的网络安全角度考虑。李四为该测试网络设定了安全组入网策略。

但,为了能够让测试环境搭建更加顺畅,在测试过程中选择开放所有端口。之后真正在试点项目部署的时候再进行调整。(这里有一定精力的话,张三建议李四还是能够1:1模拟生产环境情况,防止遗漏重点配置)

resource "alicloud_security_group" "default" {
  name = "default"
  vpc_id = alicloud_vpc.vpc.id
}

resource "alicloud_security_group_rule" "allow_all_tcp" {
  type              = "ingress"
  ip_protocol       = "tcp"
  nic_type          = "intranet"
  policy            = "accept"
  port_range        = "1/65535"
  priority          = 1
  security_group_id = alicloud_security_group.default.id
  cidr_ip           = "0.0.0.0/0"
}

需求3: 设置负载均衡

# 创建负载均衡实例,为其分配公网IP。在本示例中,为负载均衡实例配置了从前端80端口到后端8080端口的映射,并输出公网IP用于后续测试。

李四为测试环境配置了slb,选择slb.s2.small型号进行测试。 并且设定linster,80作为默认端口。

resource "alicloud_slb" "slb" {
    load_balancer_name          = "test-slb-tf"
    load_balancer_spec = "slb.s2.small"
    vswitch_id = alicloud_vswitch.vsw.id
    address_type = "internet"
}

resource "alicloud_slb_listener" "http" {
  load_balancer_id = alicloud_slb.slb.id
  backend_port = 8080
  frontend_port = 80
  bandwidth = 10
  protocol = "http"
  sticky_session = "on"
  sticky_session_type = "insert"
  cookie = "testslblistenercookie"
  cookie_timeout = 86400
  health_check="on"
  health_check_type = "http"
  health_check_connect_port = 8080
}

需求4:设置弹性伸缩

李四和王五聊了下,根据王五的反馈,一般的项目组都需要一个默认的HelloWorld应用,王五希望李四能够在交付基础设施的时候也同步交付这个共性业务,这样不需要重复每次搭建,从而进一步加速业务迭代效率。

因此,李四做了如下思考:

# 伸缩组:在模板中指定伸缩最小为2,最大为10,并将伸缩组与新建的负载均衡实例绑定。由于伸缩组的配置要求SLB必须有相应配置的监听器,因此模板需要同步指定了部署顺序。

# 伸缩组配置:在模板中指定ECS实例的具体配置。在初始化配置(user-data)中生成一个Hello World的网页,并在80端口提供服务。

resource "alicloud_ess_scaling_group" "scaling" {
  min_size = 2
  max_size = 10
  scaling_group_name = "tf-scaling"
  vswitch_ids = alicloud_vswitch.vsw.*.id
  loadbalancer_ids = alicloud_slb.slb.*.id
  removal_policies   = ["OldestInstance", "NewestInstance"]
  depends_on = ["alicloud_slb_listener.http"]
}

resource "alicloud_ess_scaling_configuration" "config" {
  scaling_group_id = alicloud_ess_scaling_group.scaling.id
  image_id = "ubuntu_18_04_64_20G_alibase_20190624.vhd"
  instance_type = "ecs.n1.medium"
  security_group_id = alicloud_security_group.default.id
  active= true
  enable= true
  user_data = "#!/bin/bash\necho \"Hello, World\" > index.html\nnohup busybox httpd -f -p 8080&"
  internet_max_bandwidth_in =10
  internet_max_bandwidth_out =10
  internet_charge_type = "PayByTraffic"
  force_delete= true
}

resource "alicloud_ess_scaling_rule" "rule" {
  scaling_group_id = alicloud_ess_scaling_group.scaling.id
  adjustment_type  = "TotalCapacity"
  adjustment_value = 2
  cooldown = 60
}

需求5: 生产完成后配置能够一键复制

李四为了杜绝之前从控制台复制信息经常出错的尴尬情况。特意在脚本最后自动化的输出一些基本信息,从而未来可以一键复制给王五。 省心省力。

output "slb_public_ip"{
  value = alicloud_slb.slb.address
}

output "alicloud_vswitch"{
  value = alicloud_vswitch.vsw
}

output "alicloud_security_group_rule"{
  value = alicloud_security_group_rule.allow_all_tcp
}

output "alicloud_ess_scaling_group"{
  value = alicloud_ess_scaling_group.scaling
}

output "alicloud_ess_scaling_ecs_instance_type"{
  value = alicloud_ess_scaling_configuration.config.instance_type
}

output "alicloud_ess_scaling_ecs_image_id"{
  value = alicloud_ess_scaling_configuration.config.image_id
}

output "alicloud_ess_scaling_ecs_internet_charge_type"{
  value = alicloud_ess_scaling_configuration.config.internet_charge_type
}

一番努力后,李四终于可以打个yes,敲个回车就完成业务生产了。

image.png

之后一键复制屏幕上的配置信息,邮件回复王五。 分分钟搞定。

image.png

以往这些各种配置,李四需要在控制台翻箱倒柜半天才能在记事本写全,还往往写错。眼都花了。这下一个回车+复制粘贴搞定,别提多开心了。

7. 总结

至此,李四逐步意识到,自己正在逐渐走上快车道。离躺着办公距离不远了。

基础设施自动化帮助李四完成了从手动工作到半自动工作的转化,将通用的业务逐步抽离出来。 让运维不再苦B。这一天,李四离开办公区,仿佛看到了幸福的未来。

但是做了多年管理的李四逐渐意识到代码化的优势非常明显,但也很可能随便下面一个运维同学一个destroy命令业务就没了。因此需要做好代码的变更和版本管理。接下来就可以进行下一步:版本管理的搭建。

8. 备注

如果需要管理terraform的多个版本并且来回切换,可以使用tfversion

切换tf版本
brew install tfenv 

tfenv --version
tfenv 2.2.2 

tfenv install 0.14.3

tfenv list
1.0.0
0.14.3
No default set. Set with 'tfenv use '

tfenv use 1.0.0
Switching default version to v1.0.0
Switching completed

9. 相关材料

阿里云Terraform官网

Gitlab官网

Gitlab-runner

Hashicorp/terraform docker镜像

Docker安装

阿里云镜像服务


作者介绍
目录