运维 用 Terraform 自动化构建基础设施

heroyct · 2018年12月12日 · 最后由 heroyct 回复于 2018年12月14日 · 505 次阅读

目前为了更快的开发产品,现在很多项目都对基础设施进行了代码化(Infrastructure as Code)。

现在的项目中使用Terraform对基础设施进行了代码化,分享下Terraform的使用。

为什么要让基础设施代码化

在使用Terraform之前,基本上是在AWS管理画面进行操作或者用AWS CLI写一些脚本来构建。

主要有以下一些问题

  • 在AWS的管理画面上面操作,比较费时间
  • 不容易管理每个人AWS的操作记录
  • 对操作的审查比较麻烦,容易误操作
  • 使用了哪些AWS的资源必须一个一个查看,不容易对整体进行把握

用Terraform可以比较好的解决以上问题,以下是用Terraform修改的流程

  1. 把需要修改的部分用Terraform代码写好,然后Pull Request
  2. 相关人员进行代码审查(Code Review)
  3. 没问题的话merge,然后在CI自动执行

好处是修改流程类似app修改的流程,大家很容易上手。

操作时间短,所有的更改记录都进行了版本管理,容易对修改进行审查。

使用了什么资源,看代码一目了然。

什么是Terraform

开发了Vagrant的hashicorp公司开发的用代码来管理基础设施的一个工具,支持绝大多数的平台。查看支持的平台

我觉的最大的优点是学习成本低,非常简单

只需要了解三个概念就完全可以进行开发了。

开发文档可以在这里查看,很多sample,很多时候稍微修改一下就可以用

1. resource

对应于aws的resouce

# 建立VPC
resource "aws_vpc" "app" {
  cidr_block                       = "10.1.0.0/16"
  assign_generated_ipv6_cidr_block = "true"

  tags {
    Name = "sample-vpc"
  }
}

# 建立ecs cluster
resource "aws_ecs_cluster" "foo" {
  name = "white-hart"
}

2. data

有时候需要从AWS中获取信息的时候可以使用data

比如获取目前操作中的AWS账号信息

data "aws_caller_identity" "current" {}

3. 变量

# 定义变量
variable "region" {
  default = "sample-region"
}
variable "access_key" {}
variable "secret_key" {}

# 使用变量
provider "aws" {
    access_key = "${var.access_key}"
    secret_key = "${var.secret_key}"
    region = "${var.region}"
}

执行Terraform

Terraform会执行当前文件夹下面的所有.tf文件

预执行,不会对AWS作出任何改动,可以确认下下有哪些改变

$ terraform plan

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + module.shared_fluentd.aws_vpc.app
      id:                               <computed>
      arn:                              <computed>
      assign_generated_ipv6_cidr_block: "true"
      cidr_block:                       "10.1.0.0/16"
      tags.Name:                        "sample-vpc"

Plan: 1 to add, 0 to change, 0 to destroy.

实际执行,这里会再次输出有哪些改变,然后输入 yes 就会在AWS上面进行构建

$ terraform apply

一些技巧总结

1. 使用module

比如要同时创建sandbox和production的fluentd服务器,基本都是一样的,只是一些参数不同。

这时候就可以使用module来归类类似的代码,然后传入变量来构建。

比如要同时创建sandbox和production的的fluentd服务器。

# 文件结构
terraform
├── modules
│   ├── fluentd
│   │   ├── main.tf
├── production_instance.tf
├── sandbox_instance.tf
# terraform/sandbox_instance.tf
module "sandbox_fluentd" {
  source                   = "./modules/fluentd"
  vpc_id                   = "your sandbox vpc id"
}

# terraform/production_instance.tf
module "production_fluentd" {
  source                   = "./modules/fluentd"
  vpc_id                   = "your production vpc id"
  # 其他的变量
}

这时候可以指定执行的对象来缩小执行范围。

terraform plan -target module.shared_fluentd
terraform plan -target module.production_fluentd

2. 按照resource分类文件

写在一个文件里面虽然也可以执行,但是内容多的时候,阅读起来不太容易,这个时候可以分成几个文件。

比如按照aws resource,变量,data来分类。

├── fluentd
│   ├── cloud_watch.tf
│   ├── data.tf
│   ├── ecs.tf
│   ├── security_group.tf
│   ├── task_role.tf
│   └── variable.tf

3. 使用depends_on来指定依赖

用的很少,基本不用指定,只有必须当某个操作依赖于另外一个操作时才用。

比如在使用AWS Service Discovery的时候,必须当aws_service_discovery构建以后,才可以获得被创建的DNS,这个时候就可以使用depends_on

data "aws_route53_zone" "fluentd" {
  name       = "${aws_service_discovery_public_dns_namespace.fluentd.name}"
  depends_on = ["aws_service_discovery_public_dns_namespace.fluentd"]
}

4. 从已有的环境生成terraform代码

官方没有提供这个功能,有人做了个GEM,用了一下,AWS基本都可以自动生成代码

terraforming

如果你已经构建好了环境,可以用这个来自动生成代码,避免打字手酸。

总结

简单介绍了Terraform的优点和基本使用方法。

我觉的它最大的优点是学习成本低,使用方便。

如果你想简单高效的构建你的基础设施,可以考虑使用terraform。

共收到 5 条回复

很方便的工具,很好用

terraform apply vs terraform destroy 都得考虑, 团队上的话需要考虑好 terraform destroy 的问题, 所以有了 Terraform Collaboration for Everyone

@wppurking

Terraform Collaboration for Everyone 目前还没用过,还没感觉到使用的必要性(以后也许会)

terraform apply目前是在sandbox构建以后,merge到mater,然后自动在CI上面进行

也许有点多余了,让固定的一个人从本地执行也许就够了,毕竟更改不是那么频繁

terraform destroy基本只在sandbox测试的时候用,production目前还没用到

@heroyct 那现在核心是 "让一人负责基础设施" 的部署, 小团队没有问题, 再大一点的团队可能会有基础设施的构建权限或者基础设施的变化的问题.

terraform destroy 的存在心里还是很怕的, 基础设施越大这个担心越可怕, 所以如果有 Terraform Collaboration for Everyone 将 terraform 的最后执行在类似 github 那样允许的 merge 操作会放心很多. 有时候不是故意, 而是运维会"手抖 + tab 补全", 然后整个基础设施就全部通过 API destroy 掉了 - -||

我在测试部署 DO 的时候, terraform plan/apply 很便捷, terraform destroy 很恐怖....

虽然 destroy 指令 让我很恐怖, 但现在使用 terraform 我觉得时机非常不错, terraform 开源到现在 Infrastructure as Code 的概念在现在的不同公用云已经很多都落地并且成熟. 大多数云厂商都为 hashicorp/terraform 提供了自己 API 的兼容 resource, 这使得 Infrastructure as Code 的范围扩张可以扩张得很广:

  • 基础使用的服务器 (AWS, Alicloud, TencentCloud, HuaweiCloud, 青云, DO, vultr, Linode ....)
    • VPC, 防火墙, ssh key ... (只要对应公有云有 API, 并提供 terraform 的 resource 支持)
  • 网络上的 DNS (cloudflare, dnsimple ...)
  • 对象存储 (AWS S3, S3 compatible ...) ...

可以想象一下, 所有程序运营的基础设施无论是服务器还是中间件, 都可以通过 terraform 的 code 来定义, 再利用 ansible (或者其官方的 Packer) 来解决服务器本身的初始化构建问题. 项目越大, 这套管理方法带来的收益越高.

所以推荐 terraform 还是很赞的!

@wppurking

那现在核心是 "让一人负责基础设施" 的部署, 小团队没有问题, 再大一点的团队可能会有基础设施的构建权限或者基础设施的变化的问题.

多谢回复。

是的,目前不到10个人,IAM权限没有分那么细,实际进行terraform plan限制成2个人来减少误操作。

从安全问题考虑的话,我觉的主要是在IAM对开发人员的权限进行分配。

比如一般的人员只可以执行获取resource的操作,无法删除,更改之类的

这样一般开发人员即使terraform destroy,并且输入yes以后,也不会被拉出去祭天。。

当然相应的开发就没那么方便了,如何取舍取决于你目前的团队

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册