DevOps/Terraform

[Terraform] ec2 인스턴스 생성시 사용자 데이터 실행하기

TTOII 2022. 4. 22. 18:51
728x90

✔️ 사용자 데이터

ec2 인스턴스를 만들 때 사용자 데이터를 입력하면 cloud-init이 명령을 실행해준다.

terraform에서 인스턴스를 생성할 때 user_data를 실행할 수 있도록 해보자

resource "aws_instance" "app_web" {
  ...
  user_data = 
  ...
}

 

Terraform에서 유저 데이터를 제공하는 방법은 여러가지이다.

일단 테라폼 코드에 직접 데이터를 입력하는 방법을 알아보자

 

✔️ Terraform 코드에 직접 사용자 데이터 입력

main.tf 파일의 인스턴스 리소스 블록 내에 해당 코드를 작성한다. 

resource "aws_instance" "app_web" {
    user_data = <<-EOF
    #!/bin/sh
    yum -y install httpd
    systemctl enable --now httpd
    echo "hello world" > /var/www/html/index.htm
    EOF
  }

유저 데이터를 만들 때도 이미지를 변경하는 것과 마찬가지로 인스턴스를 지웠다가 다시 생성한다.

결과를 보면 유저 데이터가 인코딩되어서 잘 전송된 것을 확인할 수 있다.

+ user_data                            = "b8ce4a42d421caa4e9d775d059d7113a89a044fd" # forces replacement
      + user_data_base64                     = (known after apply)
aws_instance.app_server: Destroying... [id=i-0724c6ec60e313705]
aws_instance.app_server: Still destroying... [id=i-0724c6ec60e313705, 10s elapsed]
aws_instance.app_server: Still destroying... [id=i-0724c6ec60e313705, 20s elapsed]
aws_instance.app_server: Destruction complete after 29s
aws_instance.app_server: Creating...
aws_instance.app_server: Still creating... [10s elapsed]
aws_instance.app_server: Still creating... [20s elapsed]
aws_instance.app_server: Still creating... [30s elapsed]
aws_instance.app_server: Creation complete after 32s [id=i-01b3622f96962f01d]
aws_eip.app_server_eip: Modifying... [id=eipalloc-0b6f01e01757604de]
aws_eip.app_server_eip: Modifications complete after 1s [id=eipalloc-0b6f01e01757604de]

이 때 설정해놓은 Outputs 값을 보면 퍼블릭 ip와 eip가 다르다. 

Apply complete! Resources: 1 added, 1 changed, 1 destroyed.

Outputs:

app_server_elastic_ip = "3.35.192.85"
app_server_public_ip = "13.124.197.77"

 

하지만, AWS console에서 직접 ec2 인스턴스 정보를 보면 퍼블릭 ip와 탄력적 ip가 같다고 나온다. 


왜 Oupputs으로 출력하면 다를까 ?

결론부터 말하면 아직 인스턴스에 eip가 연결되지 않았기 때문에 그렇다.

 

output.tf

output "app_server_elastic_ip" {
  value = aws_eip.app_server_eip.public_ip
}

output "app_server_public_ip" {
  value = aws_instance.app_server.public_ip
}

출력된 퍼블릭 ip는 아직 eip가 연결이 안되어서 ec2 인스턴스에서 가져온 퍼블릭 ip가 출력되었던 것이다.

eip가 만들어지고 연결이 되었을 때 그때서야 eip로 대치가 된다.

약간의 시간을 기다리고 두 값을 다시보면 같음을 확인할 수 있다.

 

✔️ 사용자 데이터를 메인 코드에서 분리

file() 함수를 사용하면 된다.

사용법은 간단하다.

file(path)

path에 파일의 경로를 쓰면 내용을 참조할 수 있다.

main.tf에 작성했던 코드를 주석 처리하고 file 함수를 이용해 한줄로 선언한다.

  # user_data = <<-EOF
  #   #!/bin/sh
  #   yum -y install httpd
  #   systemctl enable --now httpd
  #   echo "hello world" > /var/www/html/index.htm
  #   EOF 

  해당 내용을 주석처리하고 

  user_data = file("userdata.sh")

그리고 userdata.sh 파일을 따로 만들어 그 안에 사용할 사용자 데이터를 작성한다.

userdate.sh

    #!/bin/sh
    yum -y install httpd
    systemctl enable --now httpd
    echo "hello world" > /var/www/html/index.html

실행 해보면 방금전과 마찬가지로 우선 인스턴스를 삭제한뒤 새로운 인스턴스를 만든다.

aws_instance.app_server: Destroying... [id=i-01b3622f96962f01d]
aws_instance.app_server: Still destroying... [id=i-01b3622f96962f01d, 10s elapsed]
aws_instance.app_server: Still destroying... [id=i-01b3622f96962f01d, 20s elapsed]
aws_instance.app_server: Still destroying... [id=i-01b3622f96962f01d, 30s elapsed]
aws_instance.app_server: Destruction complete after 40s
aws_security_group.app_server_sg: Creating...
aws_security_group.app_server_sg: Creation complete after 2s [id=sg-05e8e4af95cfebad0]
aws_instance.app_server: Creating...
aws_instance.app_server: Still creating... [10s elapsed]
aws_instance.app_server: Still creating... [20s elapsed]
aws_instance.app_server: Still creating... [30s elapsed]
aws_instance.app_server: Creation complete after 32s [id=i-00fbaf268e10334a7]
aws_eip.app_server_eip: Modifying... [id=eipalloc-0b6f01e01757604de]
aws_eip.app_server_eip: Modifications complete after 1s [id=eipalloc-0b6f01e01757604de]

인스턴스 생성이 완료되고 실제로 접속해보면 아직 접속할 수 없다.
인스턴스에 접근할 수 있는 보안 그룹이 설정되지 않았기 때문이다.

 

✔️ 보안 그룹 추가하기

Terraform 코드로 보안 그룹을 추가해보자

 

Terraform Registry

 

registry.terraform.io

main.tf

vpc_security_group_ids = [aws_security_group.app_server_sg.id]

security_group.tf

resource "aws_security_group" "app_server_sg" {
  name   = "Allow SSH & HTTP"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = local.common_tags

}

결과

~ vpc_security_group_ids               = [
          - "sg-099f9baaa17c118e7",
        ] -> (known after apply)
        # (6 unchanged attributes hidden)

curl 명령을 이용해 eip로 접속해보면 index.html이 정상적으로 출력된다.

[vagrant@controller 01]$ curl 3.35.192.85
hello world
728x90