IaC(Infrastructure as Code)

Terraform 나만의 Module 만들어보기

cwchoiit 2024. 3. 10. 18:35
728x90
반응형
SMALL
728x90
SMALL

저번 시간에는 Terraform Registry에 있는 모듈을 가져다가 사용하는 것 까지는 해봤다. 이번에는 내가 스스로 모듈을 만들어서 그 모듈을 사용해보자.

 

Directory path

우선, 나의 모듈을 가지고 사용하는 테라폼 소스 코드의 구조는 다음과 같다.

 

account 라는 폴더가 하나의 모듈로서 기능을 할 것이고 그 모듈을 루트 디렉토리에 있는 main.tf 에서 사용할 것이다. 그럼 account 디렉토리에 각각의 파일을 하나씩 알아보자.

 

참고로 파일명은 정해져 있는게 아니라 관습적으로 사용되는 명칭이다. 그니까 꼭 저것을 따르지 않아도 되지만 관습이니 안 따라야할 이유도 없다.

 

versions.tf

이 파일은 테라폼과 프로바이더의 버전을 명시한 파일이다. 소스 코드는 다음과 같다.

terraform {
  required_version = ">= 0.15"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 3.45"
    }
  }
}

 

variables.tf

이 파일은 모듈에서 사용하는 변수를 정의한 파일이다. 소스 코드는 다음과 같다.

variable "name" {
  description = "The name for the AWS account. Used for the account alias."
  type        = string
}

variable "password_policy" {
  description = "Password Policy for the AWS account."
  type = object({
    minimum_password_length        = number
    require_numbers                = bool
    require_symbols                = bool
    require_lowercase_characters   = bool
    require_uppercase_characters   = bool
    allow_users_to_change_password = bool
    hard_expiry                    = bool
    max_password_age               = number
    password_reuse_prevention      = number
  })
  default = {
    minimum_password_length        = 8
    require_numbers                = true
    require_symbols                = true
    require_lowercase_characters   = true
    require_uppercase_characters   = true
    allow_users_to_change_password = true
    hard_expiry                    = false
    max_password_age               = 0
    password_reuse_prevention      = 0
  }
}

 

outputs.tf

이 파일은 모듈에서 만들어내는 outputs을 정의한 파일이다. 특정 테라폼 소스에서 어떤 모듈을 가져다가 사용할 때 모듈이 내뱉는 attribute를 참조해야 하는 경우가 많은데 그 참조할 수 있는 값들은 모듈에서 뱉어내는 output 뿐이다. 그래서 적절한 output이 중요하다.

소스 코드는 다음과 같다.

output "id" {
  description = "The AWS Account ID"
  value       = data.aws_caller_identity.this.account_id
}

output "name" {
  description = "Name of the AWS account. The account alias."
  value       = aws_iam_account_alias.this.account_alias
}

output "signin_url" {
  description = "The URL to signin for the AWS account."
  value       = "https://${var.name}.signin.aws.amazon.com/console"
}

output "password_policy" {
  description = "Password Policy for the AWS Account. `expire_passwords` indicates whether passwords in the account expire. Returns `true` if `max_password_age` contains a value greater than 0."
  value       = aws_iam_account_password_policy.this
}

 

main.tf

모듈의 main.tf 파일이다. 소스 코드는 다음과 같다.

data "aws_caller_identity" "this" {}

resource "aws_iam_account_alias" "this" {
  account_alias = var.name
}

resource "aws_iam_account_password_policy" "this" {
  minimum_password_length        = var.password_policy.minimum_password_length
  require_numbers                = var.password_policy.require_numbers
  require_symbols                = var.password_policy.require_symbols
  require_lowercase_characters   = var.password_policy.require_lowercase_characters
  require_uppercase_characters   = var.password_policy.require_uppercase_characters
  allow_users_to_change_password = var.password_policy.allow_users_to_change_password
  hard_expiry                    = var.password_policy.hard_expiry
  max_password_age               = var.password_policy.max_password_age
  password_reuse_prevention      = var.password_policy.password_reuse_prevention
}

 

README.md

이 파일은 이 모듈이 어떤 형식으로 만들어지고 무엇이 필수값이고 아닌지 또는 버전은 어떻게 되는지 이 모듈의 outputs은 무엇인지를 명시한 파일이다. 그리고 이 파일은 직접 작성한 게 아니고 terraform-docs 라는 툴을 사용했다.

 

terraform-docs

Generate Terraform modules documentation in various formats

terraform-docs.io

이 녀석을 다운받고 시키는 대로 하면 다음과 같이 날 위해 README 파일을 만들어준다.

$ terraform-docs markdown path/to/module

## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.15 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.45 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.45 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_iam_account_alias.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_account_alias) | resource |
| [aws_iam_account_password_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_account_password_policy) | resource |
| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_name"></a> [name](#input\_name) | The name for the AWS account. Used for the account alias. | `string` | n/a | yes |
| <a name="input_password_policy"></a> [password\_policy](#input\_password\_policy) | Password Policy for the AWS account. | <pre>object({<br>    minimum_password_length        = number<br>    require_numbers                = bool<br>    require_symbols                = bool<br>    require_lowercase_characters   = bool<br>    require_uppercase_characters   = bool<br>    allow_users_to_change_password = bool<br>    hard_expiry                    = bool<br>    max_password_age               = number<br>    password_reuse_prevention      = number<br>  })</pre> | <pre>{<br>  "allow_users_to_change_password": true,<br>  "hard_expiry": false,<br>  "max_password_age": 0,<br>  "minimum_password_length": 8,<br>  "password_reuse_prevention": 0,<br>  "require_lowercase_characters": true,<br>  "require_numbers": true,<br>  "require_symbols": true,<br>  "require_uppercase_characters": true<br>}</pre> | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_id"></a> [id](#output\_id) | The AWS Account ID |
| <a name="output_name"></a> [name](#output\_name) | Name of the AWS account. The account alias. |
| <a name="output_password_policy"></a> [password\_policy](#output\_password\_policy) | Password Policy for the AWS Account. `expire_passwords` indicates whether passwords in the account expire. Returns `true` if `max_password_age` contains a value greater than 0. |
| <a name="output_signin_url"></a> [signin\_url](#output\_signin\_url) | The URL to signin for the AWS account. |

 

그리고 이제 모듈을 가져다가 사용하는 루트 디렉토리에 있는 main.tf 파일을 보자.

 

main.tf

하단 소스 코드를 보자.

provider "aws" {
  region = "ap-northeast-2"
}

module "account" {
  source = "./account"

  name = "cwchoiit-terraform"
  password_policy = {
    minimum_password_length        = 8
    require_numbers                = true
    require_symbols                = true
    require_lowercase_characters   = true
    require_uppercase_characters   = true
    allow_users_to_change_password = true
    hard_expiry                    = false
    max_password_age               = 0
    password_reuse_prevention      = 0
  }
}

output "id" {
  value = module.account.id
}

output "account_name" {
  value = module.account.name
}

output "signin_url" {
  value = module.account.signin_url
}

output "account_password_policy" {
  value = module.account.password_policy
}

 

저번에는 Registry에 있는 module을 사용할 때 source 형태가 저런식이 아니었다. 그리고 이건 로컬에 있는 모듈을 사용할 때 쓰는 source 형식이다. 이 두 차이점을 잘 알아둬야한다.

 

그리고 account 라는 모듈이 필요한 속성인 name, password_policy 값을 작성한다.

output은 모듈이 주는 output을 그대로 가져다가 사용했다.

 

이 상태에서 Apply를 해보자. 다음과 같이 Apply는 정상적으로 됐다. 

 

그럼 내 계정의 Alias가 저렇게 변경됐는지 확인해보자. 다음은 그 결과이다.

 

 

결론

이렇게 로컬에서 모듈을 직접 만들어보고 사용해보았다. 모듈은 이런식으로 로컬에서도 사용가능하고 Registry에서 가져다가 사용하는 것도 된다. 그리고 한 가지 더 유용한 `terraform-docs`도 사용해봤다.

 

728x90
반응형
LIST

'IaC(Infrastructure as Code)' 카테고리의 다른 글

Terraform Provisioner/EC2 Userdata  (2) 2024.03.11
terraform_remote_state  (0) 2024.03.10
Terraform Cloud  (0) 2024.03.10
Terraform Workspace  (0) 2024.03.08
Terraform Commands (taint / untaint)  (0) 2024.03.08