Terraform 模块重用资源 (8)
  zNxK8cIqmu7p 2023年11月13日 21 0

模块重用资源介绍

Terraform 模块可以简化代码,减少代码重复的内容。使用 Terraform 模块可以重用基础设施资源。

在 Terraform 本身看来模块只不过是一个或多个资源的容器。通过 Terraform 的模块机制,对想要重用的资源进行封装,即可在别处像函数一样方便的调用。


模块代码结构

通过调用 modules 目录下的模块进行重用资源。

% tree modules 
modules
|-- base-server						// 基础服务器的模块
|   |-- main.tf						// 模块中用来管理一个或多个基础设施资源
|   |-- outputs.tf				// 模块的输出,相当于通用编程语言中的返回值。
|   `-- variables.tf			// 模块的输入,相当于通用编程语言中,函数的参数
`-- perp-ssh							// ssh 相关的模块,包括添加 ssh 公钥,开放 22 端口。
    |-- main.tf
    |-- outputs.tf
    `-- variables.tf



模块 main代码

基础服务模块 main代码

base-server/main.tf 内容

创建 EC2 实例,获取安全组ID,开放其他端口。

/*
* 基础设施模块
*/

# 数据源获取安全组ID
data "aws_security_groups" "default" {
  filter {
    name = "group-name"
    values = ["default"]
  }
}


# 创建EC2实例
resource "aws_instance" "server" {
  ami = lookup(var.amis, var.region)
  instance_type = var.instance_type
  key_name = var.ssh_key_name
  user_data = var.server_script
  tags = {
    Name = var.server_name
  }
}


# 开放其他端口
resource "aws_security_group_rule" "other" {
  type = "ingress"
  from_port = var.server_port
  to_port = var.server_port
  protocol = "tcp"
  cidr_blocks = [ "0.0.0.0/0" ]
  security_group_id = data.aws_security_groups.default.ids[0]
}



Perp 设施模块 main代码

perp-ssh/main.tf 内容

获取安全组ID,创建 SSH 登陆密钥,开放22端口。

/*
* 准备 SSH
*/

# 数据源获取安全组ID
data "aws_security_groups" "default" {
  filter {
    name = "group-name"
    values = ["default"]
  }
}


# 添加 SSH 登陆密钥
resource "aws_key_pair" "ssh" {
  key_name = "admin"
  public_key = file(var.public_key)
}

# 开放 22 端口,允许 SSH 登陆
resource "aws_security_group_rule" "ssh" {
  type = "ingress"
  from_port = 22
  to_port = 22
  protocol = "tcp"
  cidr_blocks = [ "0.0.0.0/0" ]
  security_group_id = data.aws_security_groups.default.ids[0]
}


模块输入

和通用编程语言中的函数具有参数相似,Terraform 模块也支持传递参数。为了使 Terraform 模块能够使用参数,只需利用 variables 文件为他什么数据变量即可。

下面代码中不包含默认的值,因而在调用模块的时候,才能传递参数。


基础服务模块 variables代码

base-server/variables.tf 内容

variable "region" {
  type = string
  description = "aws region"
}

variable "amis" {
  type = map
  description = "ami id"
}

variable "instance_type" {
  type = string
  description = "ec2 instance type"
}

variable "ssh_key_name" {
  type = string
  description = "ssh key name"
}

variable "server_name" {
  type = string
  description = "service name"
}

variable "server_port" {
  type = string
  description = "server port"
}

variable "server_script" {
  type = string
  description = "server post run script"
}



Perp 设施模块 variables代码

perp-ssh/variables.tf 内容

variable "public_key" {
  type = string
  description = "ssh public key"
}



模块输出

Terraform 模块输出的概念来自通用编程语言中函数具有返回值的想法。跟模块输入相似。只要为 Terraform 模块定义输出变量即可实现模块输出。


基础服务模块 outputs代码

base-server/outputs.tf 内容

输出基础设施的IP地址

output "ip" {
  value = aws_instance.server.public_ip
  description = "aws ec2 public ip"
}



Perp 设施模块 outputs代码

perp-ssh/outputs.tf 内容

方便其他地方引用该模块的输出属性。

output "key_name" {
  value = aws_key_pair.ssh.key_name
  description = "ssh key name"
}



模块调用

定义完成模块之后,调用模块需要使用 Terraform 提供的 module 代码块。


主服务 main代码

main.tf 内容

/*
 * 使用基础设施服务调用
*/

# 供应商
provider "aws" {          // 云供应商
  region = var.region     // 地域
}

# 调用模块,创建 ssh key
module "ssh-key-name" {
  source = "./modules/perp-ssh"

  public_key = var.public_key
}

#调用模块创建服务器 nginx
module "nginx-server" {                   // "nginx-server" 为模块名称
  source = "./modules/base-server"        // 指定本地模块路径,或者远程模块的地址
  
  server_name = "nginx-server"            // 服务器名称
  server_port = 80                        // 开放的服务器端口
  server_script = templatefile("setup-nginx.sh", { time = timestamp()})   //服务器创建后执行的脚本
  region = var.region
  amis = var.amis
  instance_type = var.instance_type
  ssh_key_name = module.ssh-key-name.key_name
}


#调用模块创建服务器 ss
module "ss-server" {
  source = "./modules/base-server"
  
  server_name = "ss-server"
  server_port = 8388
  server_script = templatefile("setup-ss.sh", { password = var.ss_password})
  region = var.region
  amis = var.amis
  instance_type = var.instance_type
  ssh_key_name = module.ssh-key-name.key_name
}



主服务 variables代码

variables.tf 内容

variable "region" {             //  变量名 region,不可用重复。花括号里面是参数
  type = string                 //  输入变量的类型
  default = "us-west-2"         //  变量的默认值
  description = "AWS region"    //  变量的描述
}

variable "amis" {
  type = map
  default = {
    us-west-2 = "ami-03f65b8614a860c29"  // ubuntu ami
  }
  description = "AWS ID"
}

variable "instance_type" {
  type = string
  default = "t2.micro"
  description = "EC2 instance type"
}

variable "public_key" {
  type = string
  default = "id_rsa.pub"
  description = "SSH public key"
}

variable "ss_password" {
  type = string
  description = "ss password"
}


主服务 outputs代码

outputs.tf 内容

这里不再引用资源的属性,而是模块的输出。

output "WEB_IP" {
  value = module.nginx-server.ip        // 这里引用模块的输出
  description = "nginx web server ip address"
}

output "SS_IP" {
  value = module.ss-server.ip
  description = "shadowsocks server ip address"
}


setup-ss.sh脚本

setup-ss.sh 内容

sudo apt update
sudo apt install -y docker.io

cat > /vat/tmp/ss-config.json <<EOF
{
    "server": "0.0.0.0",
    "server_port": 8388,
    "local_port": 1080,
    "password": "${password}",
    "timeout": 600,
    "method": "chacha20-ietf-poly1305",
    "fast_open": true
}
EOF

sudo docker run \
    -v /var/tmp:/var/tmp \
    -e ARGS='-c /var/tmp/ss-config.json' \
    -p 8388:8388 \
    -p 8388:8388/udp \
    -d \
    shadowsocks/shadowsocks-libev


setup-nginx.sh脚本

setup-nginx.sh 内容

#!/bin/bash

sudp apt update
sudo apt install -y nginx
echo Cerated: ${time} | sudo tee  /usr/share/nginx/html/index.html
exit 0

ubuntu 系统的index文件可能不是这个路径。


Terraform 部署

初始化 Terraform

首先执行命令 terraform init 初始化 terraform 以便让 terraform 下载或更新 模块。

% terraform init

Initializing the backend...
Initializing modules...
- nginx-server in modules/base-server
- ss-server in modules/base-server
- ssh-key-name in modules/perp-ssh

...

init 了上面上个服务调用的两个模块,


Apply 部署

% terraform plan
% terraform apply

  Enter a value: Wsj@123456
  Enter a value: yes
...

Apply complete! Resources: 6 added, 0 changed, 0 destroyed.

Outputs:

SS_IP = "35.91.219.161"
WEB_IP = "54.188.38.201"



验证

Terraform 模块重用资源 (8)_modules

这里还需要验证一下nginx页面,和ss容器启动情况。




使用外部模块

虽然编写 Terraform 模块并不复杂,如果有人已经分享了我们想要使用的模块,那么可以直接使用。

Terraform 除了可以保存到代码仓库之外,Terraform本身也提供了 Terraform Registry ,这是一个用来公开分发 Terraform 模块的平台,有官方和社区分享的多种模块。包括AWS,Google Cloud,阿里云等。


搜索模块

搜索 ec2-instance 选择 Modules 。

Terraform 模块重用资源 (8)_modules_02


模块首页:

Terraform 模块重用资源 (8)_Terraform_03

查看示例代码:

Terraform 模块重用资源 (8)_modules_04


使用远程模块

main.tf代码如下:

/*
*   使用外部模块
*/

provider "aws" {
  region = "us-west-2"
}

# 调用外部模块
module "ec2-instance" {
  source = "terraform-aws-modules/ec2-instance/aws"     // terraform registry 的地址
  version = "5.5.0"                                     // 模块版本

  ami = "ami-03f65b8614a860c29"                         // ec2 参数
  instance_type = "t2.micro"
  name = "myec2"
  vpc_security_group_ids = ["sg-572b3b6c"]
}


执行初始化部署

terraform init
terraform plan
terraform apply


查看

Terraform 模块重用资源 (8)_Terraform_05


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月13日 0

暂无评论

推荐阅读
  zNxK8cIqmu7p   2023年11月02日   22   0   0 terraform
  zNxK8cIqmu7p   2023年11月02日   28   0   0 terraform
  zNxK8cIqmu7p   2023年11月02日   108   0   0 IaCterraform
  zNxK8cIqmu7p   2023年11月02日   22   0   0 tfenvIaCterraform
  zNxK8cIqmu7p   2023年11月13日   18   0   0 terraform
  zNxK8cIqmu7p   2023年11月02日   36   0   0 terraform
  zNxK8cIqmu7p   2023年11月13日   19   0   0 terraform
  zNxK8cIqmu7p   2023年11月13日   16   0   0 terraform