Terraform Import를 고민하게 된 계기

내가 입사 하기 전에 AWS 클라우드에 Prod, Stage 환경이 구축이 되어 있었다.
AWS Console에서 작업을 진행하거나 shell scripts를 통해서 생성된 리소스들이 대부분 이였다.
구축에 대한 히스토리 및 스크립트에 대한 설명을 확인 할 수 없었다.
Terraform 스터디를 진행하면서 기존의 리소스 및 정보들을 Terraform 코드로 변환하고자 하는 욕구(?) 의지가 끌어 올랐다.

Terraform Import 란?

Terraform에서 Import는 Terraform을 통해서 생성된 Resource가 아니라 AWS Console을 통해서 직접 추가한 Resource나 다른 Terraform 환경에서 생성한 Resource를 가져오기 위해 제공되는 CLI 명령이다.
사용하는 이유는 Terraform은 tfstate파일에 있는 Resource만 본다는 점 때문이다.

  • Terraform에서 resouce나 module를 활용해서 생성 하려고 하면 기존 데이터가 삭제 될 수 도 있기 때문에 접근하기 쉽지 않다.
  • 이럴 때 terraform import 를 통해서 해결 가능하다

AWS IAM User에 대한 Resource 가져오기

  • AWS IAM UserList
  • Terraform을 통해서 생성한 유저가 아니면 테라폼은 수정 및 삭제를 진행 할 수 없다.
  • Terraform 스크립트로 신규 생성하려고 해도 다음과 같은 기존 유저가 있다는 에러를 반환한다.
  • Terraform은 이런 경우에 쓰기 좋은 명령어이다.
    하지만 Resource를 생성하지 않고 import만 수행 할 경우 다음과 같은 에러가 발생한다.
$ terraform import aws_iam_user.bob bob
Error: resource address "aws_iam_user.bob" does not exist in the configuration.

Before importing this resource, please create its configuration in the root module. For example:

resource "aws_iam_user" "bob" {
  # (resource arguments)
}
  • main.tf에 resource가 들어갈 공간을 만들어 준 후 실행하면 에러 없이 실행된다.
resource "aws_iam_user" "bob" {
  # (resource arguments)
}
$ terraform import aws_iam_user.bob bob
aws_iam_user.bob: Importing from ID "bob"...
aws_iam_user.bob: Import prepared!
  Prepared aws_iam_user for import
aws_iam_user.bob: Refreshing state... [id=bob]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
  • terraform.tfstate 파일에서도 리소스에 대한 정보가 정상적으로 갖고 왔음을 확인 할수 있다.
{
  "version": 4,
  "terraform_version": "1.3.2",
  "serial": 1,
  "lineage": "XXXXXXX",
  "outputs": {},
  "resources": [
    {
      "mode": "managed",
      "type": "aws_iam_user",
      "name": "bob",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "arn": "arn:aws:iam::XXXXXXXX:user/bob",
            "force_destroy": null,
            "id": "bob",
            "name": "bob",
            "path": "/",
            "permissions_boundary": null,
            "tags": {
              "level": "mid",
              "manager": "XXXXX"
            },
            "tags_all": {
              "level": "mid",
              "manager": "XXXXXX"
            },
            "unique_id": "XXXXXX"
          },
          "sensitive_attributes": [],
          "private": "XXXXXXXXXXXXX=="
        }
      ]
    }
  ],
  "check_results": null
}
  • 다른 작업 이후 terraform plan을 진행 하였을 때 다음과 같이 bob에 대한 리소스가 삭제 된다는 내용을 확인 할 수 있다.
    • import를 수행 할때 bob에 대한 정의를 하지 않고 수행 하였기 때문에 발생한 것이다.
    • import 하기 전 얻고자 하는 리소스에 대한 정의를 작성하고 import받아야 위와 같은 상황이 발생하지 않는다.
terraform plan                                  
aws_iam_user.bob: Refreshing state... [id=bob]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  - destroy

Terraform will perform the following actions:

  # aws_iam_user.bob will be destroyed
  # (because aws_iam_user.bob is not in configuration)
  - resource "aws_iam_user" "bob" {
      - arn       = "arn:aws:iam::xxxxx:user/bob" -> null
      - id        = "bob" -> null
      - name      = "bob" -> null
      - path      = "/" -> null
      - tags      = {
          - "level"   = "mid"
          - "manager" = "xxxxx"
        } -> null
      - tags_all  = {
          - "level"   = "mid"
          - "manager" = "xxxxx"
        } -> null
      - unique_id = "xxxxx" -> null
    }

Plan: 0 to add, 0 to change, 1 to destroy.

S3 Resource 가져오기

  • AWS S3 버킷 정보를 확인한다
  • Terraform import 를 실행하기 전에 Terraform 스크립트에서 리소스를 정의한다
resource "aws_s3_bucket" "main" {
  bucket        = "mybucket-s3-louis"
  acl           = "private"
  force_destroy = true
}
  • Terraform import를 실행해서 정의한 리소스에 import 한다
    • terraform import 'aws_s3_bucket.main' mybucket-s3-louis
$ terraform import 'aws_s3_bucket.main' mybucket-s3-louis
aws_s3_bucket.main: Importing from ID "mybucket-s3-louis"...
aws_s3_bucket.main: Import prepared!
  Prepared aws_s3_bucket for import
aws_s3_bucket.main: Refreshing state... [id=mybucket-s3-louis]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
  • terraform plan으로 정의한 리소스에 기존 S3 리소스가 반영 된 것을 확인 할 수 있다.
$ terraform plan
aws_s3_bucket.main: Refreshing state... [id=mybucket-s3-louis]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_s3_bucket.main will be updated in-place
  ~ resource "aws_s3_bucket" "main" {
      + acl                         = "private"
      + force_destroy               = true
        id                          = "mybucket-s3-louis"
        tags                        = {}
        # (9 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.
╷
│ Warning: Argument is deprecated
│ 
│   with aws_s3_bucket.main,
│   on main.tf line 11, in resource "aws_s3_bucket" "main":
│   11:   acl           = "private"
│ 
│ Use the aws_s3_bucket_acl resource instead
│ 
│ (and one more similar warning elsewhere)

Terraforming을 활용해보자

to be continue...

참고

https://developer.hashicorp.com/terraform/cli/commands/import
https://github.com/dtan4/terraforming
https://ch4njun.tistory.com/181
https://medium.com/@cheekorkind/terraform-import정리-aws콘솔에서-클릭으로-만든건데-반영안될까-d3852b0701d9

profile
인프라 운영하는 개발자

0개의 댓글

Powered by GraphCDN, the GraphQL CDN