1x摄影

Terraform学习笔记

admin 36

为了能够在本机更快速、高效执行TF脚本,本文先做一个配置,来实现加速相关Provider下载。

一、加速AliyunProvider读取

每次运行terraforminit命令时,Terraform会下载部署所需要的Provider,每次下载耗时很长,我们可以提前下载好Provider,例如下载到/srv/terraform-plugins目录下(Provider下载路径)

注意:目录格式如下:

1.1使用Provider缓存

添加环境变量:

exportTF_PLUGIN_CACHE_DIR="/srv/terraform-plugins"

在~/.terraformrc中增加plugin_cache_dir:

注意:配置完之后,可以通过命令行查看是否生效:

ConfiguretheAlicloudProviderterraform{required_providers{alicloud={source="aliyun/alicloud"version="1.127.0"}}required_version="=0.12"}provider"alicloud"{access_key="需要有权限访问OSS与OTS,其中OTS是用于加锁,oss是保存state数据ecs_role_name="EcsRamRole"}}
4.2Provisioner:在机器上执行操作的组件

Provisioner通常用来在本地机器或者登陆远程主机执行相关的操作,如local-execprovisioner用来执行本地的命令,chefprovisioner用来在远程机器安装,配置和执行chefclient,remote-execprovisioner用来登录远程主机并在其上执行命令。

Provisioner通常跟Provider一起配合使用,provider用来创建和管理资源,provisioner在创建好的机器上执行各种操作。

思考:结合Provider+Provisioner就可以实现基础设施层面的IaC加上应用配置层面的。完整的一套配置管理工具

4.3Module:简化你的TF模板

Module是Terraform为了管理单元化资源而设计的,是子节点,子资源,子架构模板的整合和抽象。在实际复杂的技术架构中,涉及到的资源多种多样,资源与资源之间的关系错综复杂,资源模版的编写,扩展,维护等多个问题的成本都会不断增加。将多种可以复用的资源定义为一个module,通过对module的管理简化模板的架构,降低模板管理的复杂度,这就是module的作用。

对资源进行分类,将每一类资源用一个单独的目录进行管理,最后用一个模板来管理所有的目录,进而完成对所有资源及资源关系的串联,如下所示:

├──├──├──├──modules/│├──vpc/││├──││├──││├──│├──slb/││├──││├──││├──│├──ecs/│├──rds/│├──oss/

接下来,用统一的模版将这些目录关联起来,如下所示:

//VPCmodulemodule"vpc"{source="./modules/vpc"name="new-netwtok"}//WebTiermodulemodule"web"{source="./modules/ecs"instance_count=2vswitch_ids="${_vswitch_ids}"}
4.4语法

4.4.1数据类型

JSON格式

TF语法

Boolean

booltrue/false

Number

number

String

string

EOT

hello

world

EOT

如果要保持格式可以这样写:

value=-EOT

hello

world

EOT

生成JSON或YAML。可以通过关键字jsonencode如:

example=jsonencode(

{

a=1

b="hello"

})

Object

map(){name="",age=52}

["keyname"]获取map中的值

Array

list()["",""]

[3]获取第三个元素值

Null

null不带引号的符号表示null

逻辑指令

%{ifBOOL}/{else}/{if}

"Hello,%{!=""}${}%{else}unnamed%{if}"

%{forNAMEinCOLLECTION}/%{for}

EOT%{foripinaws_*.private_ip}server${ip}%{for}EOTEOT%{foripinaws_*.private_ip~}server${ip}%{for~}EOT

操作符

*/%+-====!=||

内置函数。min()keys()

三元表达式:condition?true:false

for表达式.[:upper(s)],[fork,:length(k)+length(v)]

locals{admin_users={forname,:name=_admin}regular_users={forname,:name=userif!_admin}}

Groupingresults

variable"users"{type=map(object({role=string}))}locals{users_by_role={forname,:=name}}

内转函数

Encoding

String

Numeric

Collection

Filesystem

HashandCrypto

IPNetwork

DateTime

4.4.2代码注释

支持几种类型:

//或list(string)default=""description=""}variable"availability_zone_names"{type=list(string)default=["us-west-1a"]}variable"docker_ports"{type=list(object({internal=numberexternal=numberprotocol=string}))default=[{internal=8300external=8300protocol="tcp"}]}variable"user_information"{type=object({name=stringaddress=string})sensitive=true}resource"some_resource""a"{name=_=_}

变量类型支持:

listTYPE

setTYPE

mapTYPE

object

tuple

output

output"application_account_id"{value=""description="Outputapplicationaccountid."sensitive=truedeps_on=["",""]}

local

locals{Commontagstobeassignedtoallresourcescommon_tags={Service=_nameOwner=}}tags=_tags}

相关参数说明

resource

resource"aws_instance""server"{count=4Createoneinstanceforeachsubnetcount=length(_ids)ami="ami-a1b2c3d4"instance_type=""subnet_id=_ids[]tags={Name="Server${}"}}

terraform

terraform{back"oss"{bucket="bucket-with-terraform-state"prefix="path/mystate"key="1.tfstate"region="cn-hangzhou"tablestore_point=""tablestore_table="statelock"#是为了做OSS的权限用的ecs_role_name="EcsRamRole"}required_providers{alicloud={source="aliyun/alicloud"version="1.127.0"}}required_version="=0.12"}
4.5代码片段赏析

TBD

五、解决方案5.1纳管存量资源

这个解决方案用于以下4个场景:

场景一:长期使用控制台、阿里云CLI、资源编排服务或者直接调用API创建和管理资源,初次使用Terraform的场景。

场景二:长期使用Terraform管理资源,如果通过控制台对单个云资源做属性变更,希望保持原有的资源状态(State)一致的场景。

场景三:所有资源都定义在一个模板中,想要对原有模板进行重构拆分,以降低随着资源不断增多而带来的模板和state的管理复杂度的场景。

场景四:想要将新版Provider中新增的参数同步到原文档中的场景。

Terraform对资源的导入可以分为三个步骤:

获取资源ID:基于资源ID查询资源并获取其属性。


1、获取资源ID。对资源ID的获取可以通过Web控制台,CLI,API等多种方式,最简单的方式是通过Terraform的DataSource,输入简单的查询条件,例如获取一个ECS实例:

$tfimportalicloud__:ImportingfromID"i-bp18s06o9bc53n32"alicloud_:Importprepared!Preparedalicloud_instanceforimportalicloud_:Refreshingstate[id=i-bp18s06o9bc53n32]Importsuccessful!gedbyTerraform.

3、补齐资源模板定义。由于模板中没有完成对所导入资源的详细定义,因此,资源导入成功后,模板内容与State存储的内容存在差异(State里面的内容是完整的,但模板的内容是空白的).

为了保持资源模板与资源状态的一致,需要在模板中手动补齐缺失的参数定义,直到运行plan不会再有变更信息为止.所要补齐的内容主要以那些引起更新的字段为主,补齐完成后运行terraformplan进行测试:

在执行plan之后直到出现Nochanges表示完成
5.2通过TF+Ansible实现整体自动化运维

思路:TF中的provider用来创建和管理资源,provisioner在创建好的机器上执行各种操作。

5.3通过Jenkins+TF搭建基础设施的CI/CD

TBD

六、生态体系6.1合规审计:terraform-compliance

terraform-compliance用于合规审计,优点在于该插件是和provider无关的。

用户可以自定义合规规则(使用Behavior-DrivenDevelopmentBDD——目前常用的BDD测试框架有Ruby中的Cucumber,Python中的Behave等),比如“不能给任何Ram角色赋予AdministratorAccess权限”,这些规则存储在features中;

Cucumber中几个专业术语

Features文件:

Feature:功能,下面可以由多个Scenario

Scenario:场景,下面可以由多个Steps

Steps:步骤使用Given、When、Then、But、And这些关键词

Step_definitions文件:根据Features文件中的Steps编写测试代码

在Terraformplan后,将plan结果存储在.out文件中,使用terraform-compliance对两者进行比对,判断是否合规。

7、参考资料

AlibabaCloudProvider

官方手册

GOOGLE相关文章