高效管理基础设施:掌握 Terraform 的 templatefile 函数技巧

news2024/11/18 3:21:49

由于Terraform的许可证变更,我曾经担心未来的动向,但IBM宣布收购HashiCorp后,我感到有所安心。我将继续关注相关动向。

本文将介绍Terraform的内置函数templatefile

什么是templatefile函数?

templatefile函数用于读取指定路径下的模板文件,并将其内容渲染为模板,从而动态生成文本文件或配置文件。这在需要为不同环境使用稍有不同的文件时非常有用。

https://developer.hashicorp.com/terraform/language/functions/templatefileicon-default.png?t=N7T8https://developer.hashicorp.com/terraform/language/functions/templatefile

在AWS环境中,templatefile函数有几种应用方式,下面将介绍几个示例。

1.用户数据

用户数据用于EC2实例启动时的初始设置或自动执行脚本。我们可以使用templatefile函数来生成这些用户数据。

  • 目录结构和文件内容如下:
project/
├── modules/
│   └── ec2/
│        ├── main.tf
│        └── init.tpl
└── env/
    ├── prod/
    │     └── ec2/
    │          └── main.tf
    └── stage/
          └── ec2/
               └── main.tf
  • modules/ec2/main.tf

user_data中使用templatefile函数。我们指定同一目录下的模板文件init.tpl,并将packagesfile_content作为变量传递。

provider "aws" {
  region = "ap-northeast-1"
}
variable "packages" {
  type = list(string)
}
variable "file_content" {
  type = any
}
resource "aws_instance" "example" {
  ami                  = "ami-061a125c7c02edb39"
  instance_type        = "t2.micro"
  iam_instance_profile = "MySessionManagerRole"
  user_data = templatefile("${path.module}/init.tpl", {
    packages     = join(" ", var.packages)
    file_content = var.file_content
  })
}
  • modules/ec2/init.tpl

这是用于user_data的模板文件,采用cloud-config格式。在本示例中,我们使用了write_filesruncmd,但也可以通过users来创建用户。

通过在init.tpl中设置cloud_final_modules,可以确保即使在删除了用户数据生成的文件或卸载了软件包后,系统在重启时仍会重新创建文件或重新安装软件包。

注意:如果修改了这个模板文件并重新执行terraform apply以更改现有EC2实例的配置,用户数据会被修改,但不会被执行。若要执行新的用户数据,需要在EC2实例上运行cloud-init clean以重置cloud-init缓存,然后重新启动实例。

#cloud-config
cloud_final_modules:
 - [scripts-user, always]
 - [write-files, always]
write_files:
  - path: /etc/welcome.txt
    permissions: '0644'
    owner: root:root
    content: |
      ${file_content}
runcmd:
  - yum install -y ${packages}
  • env/prod/ec2/main.tf

prod环境的EC2实例中,指定了要创建的文件内容和安装的软件包。

module "ec2-instance" {
  source = "../../../modules/ec2"
  packages = ["amazon-cloudwatch-agent", "git"]
  file_content = <<EOF
    Welcome to prod server!
EOF
}
  • env/stage/ec2/main.tf

除了packagesfile_content外,其余内容与env/prod/main.tf相同。

module "ec2-instance" {
  source = "../../../modules/ec2"
  packages = ["git"]
  file_content = <<EOF
    Welcome to stage server!
EOF
}

env/prod/ec2/目录下执行terraform apply以创建EC2实例。以下是prod环境中EC2实例的用户数据、文件和软件包的确认结果。

prod环境EC2实例 

同样地,在 env/stage/ec2/ 目录下执行 terraform apply
以下是 stage 环境 EC2 实例的用户数据、文件和软件包的检查结果。

 stage环境EC2实例 

 2.IAM 策略与角色

main.tf 文件中描述 IAM 策略和角色会导致文件逐渐变大,每次添加新的策略或角色时,查找目标策略或角色会变得更加麻烦。
为了避免这种情况,我们可以使用 templatefile 函数。

  • 目录结构
project/
├── modules/
│   └── iam/
│        ├── main.tf
│        ├── iam_policy.json.tpl
│        └── iam_role.json.tpl
└── env/
    ├── prod/
    │     └── iam/
    │          └── main.tf
    └── stage/
          └── iam/
               └── main.tf
  • modules/ec2/main.tf

aws_iam_policy 资源的 policyaws_iam_role 资源的 assume_role_policy 中使用 templatefile 函数。
指定同一目录下的模板文件 iam_policy.json.tpliam_role.json.tpl,其中 iam_policy.json.tpl 使用 actionsresources 作为变量,iam_role.json.tpl 使用 service 作为变量。

variable "policies" {
  description = "List of IAM policies"
  type = list(object({
    name      = string
    actions   = list(string)
    resources = list(string)
  }))
}
variable "roles" {
  description = "List of IAM roles"
  type = list(object({
    name    = string
    service = string
    policies = list(string)
  }))
}
resource "aws_iam_policy" "example" {
  for_each = { for p in var.policies : p.name => p }
  name     = each.value.name
  policy   = templatefile("${path.module}/iam_policy.json.tpl", {
    actions   = jsonencode(each.value.actions)
    resources = jsonencode(each.value.resources)
  })
}
resource "aws_iam_role" "example" {
  for_each = { for r in var.roles : r.name => r }
  name               = each.value.name
  assume_role_policy = templatefile("${path.module}/iam_role.json.tpl", {
    service = each.value.service
  })
}
resource "aws_iam_role_policy_attachment" "example" {
  for_each = { for r in var.roles : r.name => r }
  role       = aws_iam_role.example[each.key].name
  policy_arn = lookup({ for p in var.policies : p.name => aws_iam_policy.example[p.name].arn }, each.value.policies[0])
}
  • modules/iam/iam_policy.json.tpl

这是用于 policy 的模板文件。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ${actions},
      "Resource": ${resources}
    }
  ]
}
  • modules/iam/iam_role.json.tpl

这是用于 assume_role_policy 的模板文件。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "${service}"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
  • env/prod/iam/main.tf

prod 环境中描述要创建的 IAM 策略和角色。

module "iam" {
  source = "../../../modules/iam"
  policies = [
    {
      name      = "prod_policy_1"
      actions   = ["s3:ListBucket", "s3:GetObject"]
      resources = ["arn:aws:s3:::prod-bucket-name", "arn:aws:s3:::prod-bucket-name/*"]
    },
    {
      name      = "prod_policy_2"
      actions   = ["ec2:DescribeInstances"]
      resources = ["*"]
    }
  ]
  roles = [
    {
      name    = "prod_role_1"
      service = "ec2.amazonaws.com"
      policies = ["prod_policy_1"]
    },
    {
      name    = "prod_role_2"
      service = "lambda.amazonaws.com"
      policies = ["prod_policy_2"]
    }
  ]
}
  • env/stage/iam/main.tf

stage 环境中描述要创建的 IAM 策略和角色。

module "iam" {
  source = "../../../modules/iam"
  policies = [
    {
      name      = "stage_policy_1"
      actions   = ["s3:ListBucket", "s3:GetObject"]
      resources = ["arn:aws:s3:::stage-bucket-name", "arn:aws:s3:::stage-bucket-name/*"]
    },
    {
      name      = "stage_policy_2"
      actions   = ["ec2:DescribeInstances"]
      resources = ["*"]
    }
  ]
  roles = [
    {
      name    = "stage_role_1"
      service = "ec2.amazonaws.com"
      policies = ["stage_policy_1"]
    },
    {
      name    = "stage_role_2"
      service = "lambda.amazonaws.com"
      policies = ["stage_policy_2"]
    }
  ]
}

 在 `env/prod/iam/` 目录下执行 `terraform apply` 以创建 IAM 策略和角色。  
以下是 `prod` 环境 IAM 策略和角色的检查结果。

prod環境IAM-1 

 

prod環境IAM-2 

同样,在 env/stage/iam/ 目录下执行 terraform apply
以下是 stage 环境 IAM 策略和角色的检查结果。

 

  stage環境IAM-1

 stage環境IAM-2

3.Terraform 配置文件

Terraform 配置文件的扩展名为 .tf,包括定义基础设施资源的 main.tf、声明变量的 variables.tf 和定义输出值的 outputs.tf 等文件。
通过使用 templatefile 函数,可以动态地生成 Terraform 配置文件(.tf 文件)。
※ 由于 Terraform 会读取目录中的所有 .tf 文件,因此只要扩展名是 .tf,文件名可以自由更改。

  • 目录结构
project/
├── modules/
│   └── s3/
│        ├── main.tf
│        └── s3.tf.tpl
└── env/
    ├── prod/
    │     └── s3/
    │          └── main.tf
    └── stage/
          └── s3/
               └── main.tf
  • modules/s3/main.tf

local_file 资源的 content 中使用 templatefile 函数。
指定同一目录下的模板文件 s3.tf.tpl,其中 bucket_name 是模板中的变量。

provider "aws" {
  region = "ap-northeast-1"
}
variable "bucket_names" {
  type = list(string)
}
variable "file_path" {
  type = string
}
resource "local_file" "s3_buckets" {
  count    = length(var.bucket_names)
  filename = "${var.file_path}/s3_${var.bucket_names[count.index]}.tf"
  content  = templatefile("${path.module}/s3.tf.tpl", {
    bucket_name = var.bucket_names[count.index]
  })
}
  • modules/s3/s3.tf.tpl

这是用于 content 的模板文件。

resource "aws_s3_bucket" "${bucket_name}" {
  bucket = "${bucket_name}"
  acl    = "private"
}
  • env/prod/s3/main.tf

prod 环境中描述要创建的 S3 存储桶。

module "s3" {
  source = "../../../modules/s3"
  
  bucket_names = ["prod-bucket-example-1", "prod-bucket-example-2", "prod-bucket-example-3"]
  file_path = "."
}
  • env/stage/s3/main.tf

stage 环境中描述要创建的 S3 存储桶。

module "s3" {
  source = "../../../modules/s3"
  
  bucket_names = ["stage-bucket-example-1", "stage-bucket-example-2", "stage-bucket-example-3"]
  file_path = "."
}

在 `env/prod/s3/` 目录下执行 `terraform apply` 时,将会创建 Terraform 配置文件(`prod-bucket-example-1.tf`、`prod-bucket-example-2.tf`、`prod-bucket-example-3.tf`)。  
然后再次执行 `terraform apply`,Terraform 会读取这些创建的文件并创建 S3 存储桶。  
以下是 `prod` 环境 S3 存储桶的检查结果。

 prod環境s3

 同样,在 env/stage/s3/ 目录下执行 terraform apply 两次。
以下是 stage 环境 S3 存储桶的检查结果。

stage環境S3

 

最后

本文介绍了 templatefile 函数的三种应用方法,但它还有许多其他的使用场景。
希望本文能为使用 Terraform 的大家提供参考,并帮助大家发现 templatefile 函数的新应用方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1955770.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ip2region - 基于xdb离线库的Java IP查询工具提供给脚本调用

文章目录 Pre效果实现git clone编译测试程序将ip2region.xdb放到指定目录使用改进最终效果 Pre OpenSource - Ip2region 离线IP地址定位库和IP定位数据管理框架 Ip2region - xdb java 查询客户端实现 效果 最终效果 实现 git clone git clone https://github.com/lionsou…

用SQL将数值转换为进度条

hi&#xff0c;大家好呀&#xff01; 最近天气是真的热&#xff0c;上周我们在某音做了一次直播&#xff0c;主要是讲解一下表&#xff0c;那我们最近的会在视频号&#xff0c;也就是微信上给大家直播讲解一下查询&#xff0c;直播预告晚点会分享给大家&#xff0c;请大家关注…

队列queue介绍

队列是一种常见的数据结构&#xff0c;它遵循FIFO&#xff08;先进先出&#xff09;的原则&#xff0c;即最先进入队列的元素将最先被移除。队列在Java中有多种实现方式&#xff0c;其中包括&#xff1a; 1.ArrayDeque&#xff1a;这是一个基于数组的双端队列&#xff0c;可以在…

模拟实现短信登录功能 (session 和 Redis 两种代码实例) 带前端演示

目录 整体流程 发送验证码 短信验证码登录、注册 校验登录状态 基于 session 实现登录 实现发送短信验证码功能 1. 前端发送请求 2. 后端处理请求 3. 演示 实现登录功能 1. 前端发送请求 2. 后端处理请求 校验登录状态 1. 登录拦截器 2. 注册拦截器 3. 登录完整…

Boost_Searcher测试用例编写

功能描述&#xff1a; 用户在客户端页面&#xff0c;在搜索框输入关键词&#xff0c;页面将显示Boost库中所有包含该关键词的内容。 界面功能兼容性易用性安全性性能弱网安装/卸载 编写测试用例&#xff1a; 功能&#xff1a; 在浏览器搜索框中输入ip地址与端口号&#xff0…

MySQL的库操作和表操作

文章目录 MYSQLSQL语句分类服务器&#xff0c;数据库和表的关系 库操作表操作 MYSQL SQL语句分类 DDL【data definition language】 数据定义语言&#xff0c;用来维护存储数据的结构代表指令: create, drop, alterDML【data manipulation language】 数据操纵语言&#xff0…

Playwright 的使用

Playwright 的特点 支持当前所有主流浏览器&#xff0c;包括 Chrome 和 Edge &#xff08;基于 Chromiuns&#xff09;, Firefox , Safari 支持移动端页面测试&#xff0c;使用设备模拟技术&#xff0c;可以让我们在移动Web 浏览器中测试响应式的 Web 应用程序 支持所有浏览…

做一个能和你互动玩耍的智能机器人之四--固件

在openbot的firmware目录下我们能够找到arduino的固件源码和相关的文档。 openbot的controller目录下&#xff0c;是控制器的代码目录&#xff0c;用来控制机器人做一些动作。未来的目标是加入大模型&#xff0c;使其能够理解人的语言和动作来控制。 固件代码&#xff0c;支持…

数据结构 -- 算法的时间复杂度和空间复杂度

数据结构 -- 算法的时间复杂度和空间复杂度 1.算法效率1.1 如何衡量一个算法的好坏1.2 算法的复杂度 2.时间复杂度2.1 时间复杂度的概念2.2 大O的渐进表示法2.3常见时间复杂度计算举例 3.空间复杂度4. 常见复杂度对比 1.算法效率 1.1 如何衡量一个算法的好坏 如何衡量一个算法…

数据库实验:SQL Server基本表单表查询

一、实验目的&#xff1a; 1、掌握使用SQL语法实现单表查询 二、实验内容&#xff1a; 1. 查询订购日期为2001年5月22日的订单情况。&#xff08;Orders&#xff09;&#xff08;时间日期的表达方式为 dOrderDate ‘2001-5-22’&#xff0c;类似字符串&#xff0c;使用单引号…

Linux---git工具

目录 初步了解 基本原理 基本用法 安装git 拉取远端仓库 提交三板斧 1、添加到缓存区 2、提交到本地仓库 3、提交到远端 其他指令补充 多人协作管理 windows用户提交文件 Linux用户提交文件 初步了解 在Linux中&#xff0c;git是一个指令&#xff0c;可以帮助我们做…

Python爬虫-中国汽车市场月销量数据

前言 本文是该专栏的第34篇,后面会持续分享python爬虫干货知识,记得关注。 在本文中,笔者将通过某汽车平台,来采集“中国汽车市场”的月销量数据。 具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。废话不多说,下面跟着笔者直接往下看正文详细内容。(附…

【原创】使用keepalived虚拟IP(VIP)实现MySQL的高可用故障转移

1. 背景 A、B服务器均部署有MySQL数据库&#xff0c;且互为主主。此处为A、B服务器部署MySQL数据库实现高可用的部署&#xff0c;当其中一台MySQL宕机后&#xff0c;VIP可自动切换至另一台MySQL提供服务&#xff0c;实现故障的自动迁移&#xff0c;实现高可用的目的。具体流程…

微服务-MybatisPlus下

微服务-MybatisPlus下 文章目录 微服务-MybatisPlus下1 MybatisPlus扩展功能1.1 代码生成1.2 静态工具1.3 逻辑删除1.4 枚举处理器1.5 JSON处理器**1.5.1.定义实体****1.5.2.使用类型处理器** **1.6 配置加密&#xff08;选学&#xff09;**1.6.1.生成秘钥**1.6.2.修改配置****…

哪里可以查找短视频素材?6个素材查找下载渠道分享!

在短视频的风靡浪潮中&#xff0c;不少创作者纷纷投身于这一领域&#xff0c;无论是分享生活点滴还是进行商业宣传&#xff0c;高质量的短视频内容总能吸引众多观众的目光。然而&#xff0c;精良的短视频制作离不开优质的素材支持。本文将为大家介绍6个优秀的高质量短视频素材下…

ProxmoxPVE虚拟化平台--U盘挂载、硬盘直通

界面说明 ### 网络设置 ISO镜像文件 虚拟机中使用到的磁盘 挂载USB设备 这个操作比较简单&#xff0c;不涉及命令 选中需要到的虚拟机&#xff0c;然后选择&#xff1a; 添加->USB设置选择使用USB端口&#xff1a;选择对应的U盘即可 硬盘直通 通常情况下我们需要将原有…

前端Long类型精度丢失:后端处理策略

文章目录 精度丢失的具体原因解决方法1. 使用 JsonSerialize 和 ToStringSerializer2. 使用 JsonFormat 注解3. 全局配置解决方案 结论 开发商城管理系统的品牌管理界面时&#xff0c;发现一个问题&#xff0c;接口返回品牌Id和页面展示的品牌Id不一致&#xff0c;如接口返回的…

C/C++大雪纷飞代码

目录 写在前面 C语言简介 EasyX简介 大雪纷飞 运行结果 写在后面 写在前面 本期博主给大家带来了C/C实现的大雪纷飞代码&#xff0c;一起来看看吧&#xff01; 系列推荐 序号目录直达链接1爱心代码https://want595.blog.csdn.net/article/details/1363606842李峋同款跳…

Prime Land(牛客)

计算出n-1 对n-1进行质因数分解 // Problem: Prime Land // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/21094/D // Memory Limit: 524288 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org)#include<iostream> #in…