使用Terraform对主流三朵云进行ECS批量部署

发布时间:2024年01月02日

写在前面:

terraform是一个开源的自动化创建,自动化链接的,跨运营商应用。本质是一个IaC(Infrastructure as Code)工具,这里吐槽一句,为什么不叫C2I或者I2C这样明明更顺口,笔者想了一下可能和硬件通信协议IIC(I-squared-C)要做区分吧

这个东西只需要一个模板和简单命令就可以快速创建同配置的 实例,VPC,子网,磁盘……在工作中,我们经常需要快速部署多台同配置的实例,然则手动配置一则繁琐,二则可能出错,三是跨运营商设置,所以亟需按照统一模板快速批量创建,Terraform很好的胜任这个工作,接下来笔者以EC2为例一步步用Terraform创建。

非常推荐了解一下这个,因为Terraform本质是一个跨平台的资源编排工具,无论是洋人的AWS、国内的ALI、或者是老牌VMware、OpenStack都支持这个

Terraform用HCL语言配置,是HashiCorp旗下产品,支持许多云基础设施提供商,如亚马逊AWS,微软Azure,IBM Cloud,Serverspace,Google Cloud Platform,[9]DigitalOcean,[10]Oracle Cloud Infrastructure,Yandex.Cloud,[11]VMware vSphere和OpenStack

一、配置关键词网站:

除了自己写外本人还参考了其他资料。

笔者文章只作为抛砖引玉,任何技术都推荐在官网系统性学习。

1. terraform官网:

https://www.terraform.io/downloads

2. AWS?provider:

Terraform Registryicon-default.png?t=N7T8https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance

3. ALi provider:

Terraform Registryicon-default.png?t=N7T8https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/instance

4. HW provider:

Terraform Registryicon-default.png?t=N7T8https://registry.terraform.io/providers/huaweicloud/huaweicloud/latest/docs/resources/compute_instance

5. VSphere provider:

Terraform Registryicon-default.png?t=N7T8https://registry.terraform.io/providers/hashicorp/vsphere/latest/docs

?
二、相关概念

1.?声明性语言HCL:

Terraform 使用声明性配置语言来描述所需的基础设施,而不是脚本式的命令。用户定义目标状态,而 Terraform 负责确保当前状态与目标状态一致。这句话什么意思呢?本质是说,Terraform会在本地维持一个信息控制远端服务器资源与本地一致,例如我们使用Terraform创了2个实例,然后又在服务器厂商提供的控制台改了这两个机器的配置,那么我们再次跑Terraform脚本的时候,Terraform会将远端配置更改。这样的好处是架构一旦确定,不会乱动。

2. 提供者(Providers):

Terraform 使用提供者来与不同的基础设施平台进行交互,如AWS、ALI Cloud、VMware等。每个提供者实现了与特定云服务提供商的 API 交互的功能。说白了就是Terraform虽然是一个跨平台的资源编排工具,但是其不同厂商的书写规范会有些许差异。我想这个无可厚非,毕竟各个厂商提供的服务本来也有差别。

3. 资源(Resources):

Terraform 配置文件中的资源是用户希望在基础设施中创建或管理的实体,如虚拟机、存储桶、数据库等。每个资源都由其类型和具体配置参数定义。这个概念和instance有点像,总之就是Terraform可操作的资源。

4. 模块(Modules):

模块是 Terraform 配置的可重用部分,允许将基础设施划分为较小的、更易管理的部分。模块可以包含资源、变量、输出等。这个是在说Terraform支持自写脚本后反复调用,这里引入一段HCL代码介绍一下,总之看个人习惯,如果机器多tf拆开写方便,机器少tf写成一个方便。

# 注意此代码是多个分立的文件。
# s3-module/main.tf 在 s3-module 目录中创建模块的配置文件。

provider "aws" {
  region = "us-east-1" # 修改为你的 AWS region
}

resource "aws_s3_bucket" "my_bucket" {
  bucket = var.bucket_name
  acl    = "private"
}

# s3-module/variables.tf 在 s3-module 目录中创建输入变量的定义文件。

variable "bucket_name" {
  description = "The name of the S3 bucket"
  type        = string
}

# s3-module/outputs.tf 在 s3-module 目录中创建输出值的定义文件。

output "bucket_id" {
  description = "The ID of the created S3 bucket"
  value       = aws_s3_bucket.my_bucket.id
}

# main.tf 在 main 目录中创建主 Terraform 配置文件,引用模块。这个是真正的程序主入口

provider "aws" {
  region = "us-east-1" # AWS 区域
}

module "my_s3_bucket" {
  source     = "./s3-module" # 指定模块的路径,这里是相对路径
  bucket_name = "my-unique-bucket-name" # 传递输入变量
}

output "my_s3_bucket_id" {
  value = module.my_s3_bucket.bucket_id # 引用模块的输出值
}

5. 变量(Variables):

Terraform 允许通过变量来参数化配置,使其更具灵活性和可重用性。变量可以在配置文件中定义,也可以通过外部传递的值进行设置。在上面的例子中,我们使用了一个变量文件variables.tf,可以往上翻一下看看。

6. 输出(Outputs):

输出定义了从 Terraform 管理的基础设施中提取的值。这些值可以在后续的配置文件中使用,或者通过 Terraform 命令行工具输出。

7. 状态文件(State File):

Terraform 使用状态文件来追踪当前基础设施的状态。状态文件记录了当前基础设施中所有资源的信息,以便在执行操作时可以进行计划和对比。通常以文件名 terraform.tfstate 或者是由 backend 配置指定的文件名保存

8. 计划(Plan)和应用(Apply):

在 Terraform 中,用户通过执行 terraform plan 命令来查看计划,这将显示计划的变更。然后,通过执行 terraform apply 命令来将计划应用到基础设施中。这个东西不是计划任务,而是正式变更前,可以敲一下这个命令看一下基础设施会如何更改,防止出问题。

三、Aws EC2创建示例,创建模板

0. 创建一个入口文件main.tf

创建一个main.tf文件,作为编排入口(不一定要叫main,可以随便起)

!!!注意:terraform会默认扫描工作目录(./)下的所有tf文件,所以请确保tf文件间不会干扰!!!

?

1. 设置provider(厂商设置,本次使用的是AWS)

配置AK/SK作为鉴权,设置region作为机器地域落位。

provider "aws" {
 region      = "us-east-1"
 access_key  = ""
 secret_key  = ""
} 

2.关键配置,写在resource后的{}内

PS:注意格式{},缩进不严格,默认应该是 key="value";而对于一些特别的值,比如安全组是 [];变量需要${};子项,tags或root_block_device是一个map故{}? 。也就是说[]和{}(列表和字典)沿袭了常用的语法

##创建实例,create   instance
##只需要更改“helloword”后大括号的部分即可,更多参数请看https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance

resource "aws_instance" "helloworld" {
ami           =   "ami-blabla"
instance_type = "t2.micro"
count         = "1"

#标签项: Key  = "value"
#机器名字,这里采用前缀加递增数字,名字本身可以递归,下面给出了一个例子(注释),会生成test-1,test-2……
tags = {
Name     = "test"
#Name    = "test-${count.index+1}"
CodeName = "blabla"
 }

########################如果有新参数,请参照

#https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance

#add ur codes below,添加新的代码,格式:key="value",缩进不严格

subnet_id              =   "subnet-123123f"
availability_zone      =   "us-east-1c"
#private_ip            =   "172.31.10.${count.index +1}"
#注意安全组是一个list,需要写上中括号
#security_groups       =   ["launch-1"]
vpc_security_group_ids = ["sg-0ce786"]
key_name               =   "key-123123"

#这里是磁盘设置(GB)
#类型:standard,   gp2, gp3, io1, io2, sc1, or st1.默认gp2
root_block_device {
volume_size = "8"
volume_type = "standard"
}

#磁盘标签

volume_tags = {
CodeName    = "test-disk"

 }

credit_specification {

cpu_credits = "unlimited"

 }

/*  #这里是开机后执行的命令
user_data = <<-EOF

               #!/bin/bash
               sudo apt update -y
               sudo apt install   apache2 -y
               sudo systemctl start   apache2
               sudo bash -c 'echo   your very first web server > /var/www/html/index.html'
               EOF

*/

###################################################

} 

如果你需要额外的配置,请参照文首的网址,寻找关键词以及格式添加到大括号内,如下:

?

3.输出设置:

terraform支持对生成后的实例,进行查询信息回返,这里以回返IP,ID为例,可以写成循环

#回返IP return   pub&pri ip,会打印每一个机器的ID,公私IP,NAME

output "id_ip" {

  value = {
    for index, droplet in   aws_instance.helloworld :
          droplet.id => {
public-ip      = droplet.public_ip
private-ip     = aws_instance.helloworld[index].private_ip
#id            = aws_instance.helloworld[index].id
Name		   = aws_instance.helloworld[index].tags.Name
      }
  }
}

#这一行会打印 end and   success

output "answer"{
  value = "end and   success"
} 

4.其他注意事项

(1)系统盘设置

系统盘设置设置 root_block_device是resource下的一个子项,但注意,root_block_device后没有“ = ”

磁盘标签 volume_tags并不写在root_block_device内,而是resource的一个子项map,并且需要“ = ”??

(2)机器类型错误

如果创建时发现错误400,提示not support请查看机器类型合适与否。?

三、正式运行:

常用命令有3个,这三个也是包括了实例从创建到销毁的整个生命周期。

创建好模板后,先使用 init命令(如果第一次运行),后使用plan和apply,最后destory销毁

1.terraform init

第一次运行terraform需要初始化,terraform会下载运营商提供的依赖,在工作目录生成一个.terraform文件夹

terraform init


PS:如果需要更改工作路径:terraform -chdir=./path init

2.terraform apply

根据模板创建机器,需要yes确认,如果懒得点yes,请用echo yes | terraform apply 替代。

如果希望更改terraform工作目录,请用如下命令,其中./aws是新的工作目录(由于terraform会默认扫描工作目录的所有tf文件,故常用此命令区别)

PS:更改路径 terraform??-chdir=./path??apply

PPS:强制apply:echo yes | terraform -chdir=./path apply?

terraform apply 

· apply后会生成三个文件如下图,这三个文件用于后续修改或者销毁,所以如果你需要另外创建机器,请删除这三个文件,否则terraform会默认修改之前的机器配置。

· 另外:如果您要更换运营商创建机器,也应该删除这些文件,否则terraform会认为你是在修改机器,但是之前的机器运营商不同,故而会报错?

3.terraform destory

terraform destroy

销毁之前创建的机器,依赖于上面的文件。?

四、其他运营商,代码及注意事项


1.华为云

(1)需要额外指定

????????由于非技术因素,华为的模板需要额外添加此项,否则会初始化失败,

另外:谷歌搜索huawei terraform instance 无结果,文档入口请看文首的链接,并且有理由怀疑可能未来terraform会下架,请注意保存相关页面和provider

(2)公网IP需要手动生成并绑定,并且instance项中指定子网ID(UUID)?

(3)模板代码?

##华为从terraform官网找不到了,需要添加下面这一项保证初始化成功

terraform {
 required_providers {
 huaweicloud = {
 source           =   "huaweicloud/huaweicloud"
 version          = ">= 1.20.0"
  }
 }
 required_version = ">=   0.13"
}

##认证,login account
##region对应地区,并写好AK/SK
provider "huaweicloud" {
 region     = "ap-southeast-3"
 access_key = ""
 secret_key = ""
}

##下面是具体的机器配置,缩进不严格,但注意有些项目有子项,需要大括号{}
resource "huaweicloud_compute_instance" "ecs" {
 name       = "QAQ"
 admin_pass =   "password_123123"
 #image_id  = ""
 image_name = "镜像名或者镜像ID二选一"
 flavor_id  = "s6.large.2"

 #可用区代号查询https://developer.huaweicloud.com/endpoint
 availability_zone     = "ap-southeast-3c"
 #security_groups      = ["kubg"]
 security_group_ids    = ["13dcf94"]
 count                 = "1"

 ##企业项目ID号
 enterprise_project_id =   "123123"

network {
 #UUID是子网ID
 uuid                  =   "21231212-1234-1234-1234-123412311232"
 access_network        = "true"
 }

 tags = {
 #这里可以添加自定义的标签,格式已给出
 CodeName = "pepper"
 }

 #系统盘选项,类型有SAS,SSD,GPSSD,ESSD
system_disk_type = "SAS"
system_disk_size = "40"
########################如果有新参数,请参照
#https://registry.terraform.io/providers/huaweicloud/huaweicloud/latest/docs/resources/compute_instance
#add ur codes below,添加新的代码,格式:key="value",缩进不严格
########################
}

##华为的机器需要手动绑定公网IP,下面这一项是创建EIP用的
#https://registry.terraform.io/providers/huaweicloud/huaweicloud/latest/docs/resources/vpc_eip
resource "huaweicloud_vpc_eip" "myeip" {
 publicip {
 type        = "5_bgp"
 }

 bandwidth {
 name        = "test"
 size        = "5"
 #share_type可选PER或者WHOLE
 share_type  = "PER"
 #下面这个付费类型traffic或者bandwidth
 charge_mode = "traffic"
 }
 count =   length(huaweicloud_compute_instance.ecs)
 #企业项目ID号
 #enterprise_project_id =   "11231214-1236-1230-1212-123012312321"
}


##华为的机器需要手动绑定公网IP,下面这一项是绑定机器用的
resource "huaweicloud_compute_eip_associate"   "associated" {
 count       =   length(huaweicloud_compute_instance.ecs)
 public_ip   =   huaweicloud_vpc_eip.myeip[count.index].address
 instance_id =   huaweicloud_compute_instance.ecs[count.index].id
}

#回返IP return   pub&pri ip,会打印每一个机器的ID,公私IP,NAME
output "id_ip" {
 value = {
     for index, droplet in   huaweicloud_compute_instance.ecs :
 #droplet.tags.Name => {
         droplet.id => {
 public-ip  = huaweicloud_vpc_eip.myeip[index].address
 private-ip =   huaweicloud_compute_instance.ecs[index].access_ip_v4
 Name        =   huaweicloud_compute_instance.ecs[index].name
  }
 }
}

output "answer"{
 #value = [for i in   alicloud_instance.instance: i.public_ip] # 这个代码有点久了,我不确定为什么alicloud会在这里出现,但总的来说是一个可迭代对象,换成华为对应的即可。
 value  = "end and success"
}  

2.阿里云

(1)必须要指定交换机ID,否则terraform在调用API会报错,并且不能直接分析出来??

(2)策略IP限制不要带掩码,否则会返回空信息但不报错

?????????这个错误很难定位

?

?

(3)模板代码??

##认证,login account
##region对应地区,并写好AK/SK
##阿里region表   https://help.aliyun.com/document_detail/40654.html
provider "alicloud" {
 access_key = "输入你的ak"
 secret_key = "输入你的sk"
 region     = "cn-hongkong"
}

resource "alicloud_instance" "instance" {

 image_id             = "win2016.vhd"
 instance_type        = "ecs.t5-c1m2.large"
 security_groups      =   ["sg-111","sg-222"]
 instance_name        = "ali-test-1"
 password             = "pass_11223344"
 vswitch_id           = "vsw-123"
 count                = "1"

##网络设置
##此项已弃用internet_max_bandwidth_in   = "200"
 internet_max_bandwidth_out         = "100"
##磁盘设置,
##类型可选ephemeral_ssd,cloud_efficiency,cloud_ssd,cloud_essd,cloud
 system_disk_size     = "20"
 system_disk_category =   "cloud_efficiency" #默认是效率云盘
 system_disk_name     = "mydick"

#标签项,可自由添加
tags = {
 CodeName = "game"
}

########################如果有新参数,请参照
#https://registry.terraform.io/providers/aliyun/alicloud/latest/docs/resources/instance
#add ur codes below,添加新的代码,格式:key="value",缩进不严格

availability_zone    =   "cn-hongkong-c"
host_name            =   "i12jZ"
##付费类型两种PrePaid,   PostPaid默认PostPaid,写为prepaid要指定订购时间,默认自动续订
##renewal_status为是否自动续费,AutoRenewal,Normal,NotRenewal,默认Normal
##unit可选Week,Month
##period是自动续费间隔
instance_charge_type = "PrePaid"
renewal_status       =   "Normal"
period_unit          =   "Month"
period               =   "1"
#spot策略可选NoSpot,SpotWithPriceLimit,SpotAsPriceGo
spot_strategy        =   "NoSpot"

#########################
}

#回返IP return   pub&pri ip,会打印每一个机器的ID,公私IP,NAME
output "id_ip" {
 value = {
   for index, droplet in   alicloud_instance.instance :
      droplet.id => {
 public-ip  = droplet.public_ip
 private-ip =   alicloud_instance.instance[index].private_ip
 #id        =   alicloud_instance.instance[index].id
 Name       =   alicloud_instance.instance[index].instance_name
  }
 }
}

output "answer" {
 #value = [for i in   alicloud_instance.instance: i.public_ip]
 value  = "end and success"
}  

文章来源:https://blog.csdn.net/m0_62856417/article/details/135330908
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。