✍ Posted by Immersive Builder Seong
1. 실습 소개
이번 실습에서는 테라폼을 사용하여 간단한 EC2 웹 서버를 배포합니다.
실습은 AWS 환경에서 진행하며, 작업 순서는 하기와 같습니다.
- Step1. 기본 VPC(default) 구성 확인
- Step2. 최신 AMI 이미지(Ubuntu) 가져오기
- Step3. Cloud-init Script 작성
- Step4. 테라폼 구성파일 작성
- Step5. EC2 웹 서버 배포 및 접속 테스트
2. EC2 웹 서버 배포하기
Step1. 기본 VPC 구성 확인
AWS 계정 생성 시 기본으로 구성되는 VPC/Subnet에 EC2 웹서버를 배포할 예정입니다.
따라서 기본 디폴트 VPC와 Subnet 정보를 사전에 확인합니다.
- VPC(default-vpc)
$ aws ec2 describe-vpcs --filter 'Name=isDefault,Values=true' | jq '.Vpcs[0].VpcId'
"vpc-7dac0a16"
$ aws ec2 describe-vpcs --filter 'Name=isDefault,Values=true' | jq '.Vpcs[0].Tags[0].Value'
"default-vpc"
$ aws ec2 describe-vpcs --filter 'Name=isDefault,Values=true' | jq '.Vpcs[0].CidrBlock'
"172.31.0.0/16"
- Subnets
$ aws ec2 describe-subnets --filter 'Name=vpc-id,Values=vpc-7dac0a16' --output table
|+-----------------------------+----------------------------------------------------------------+|
|| SubnetId | subnet-3b06d650 ||
|| CidrBlock | 172.31.0.0/20 ||
|+-----------------------------+----------------------------------------------------------------+|
|| SubnetId | subnet-c752dfbc ||
|| CidrBlock | 172.31.16.0/20 ||
|+-----------------------------+----------------------------------------------------------------+|
|| SubnetId | subnet-4dcbcf01 ||
|| CidrBlock | 172.31.32.0/20 ||
|+-----------------------------+----------------------------------------------------------------+|
|| SubnetId | subnet-90aef7cc ||
|| CidrBlock | 172.31.48.0/20 ||
|+-----------------------------+----------------------------------------------------------------+|
Step2. 최신 AMI 이미지 가져오기
배포할 EC2 웹 서버의 OS는 Ubuntu로 진행합니다.
데이터 소스를 정의하여 AWS에서 제공하는 최신 Ubuntu AMI 이미지를 가져올 수 있습니다.
데이터 소스란 테라폼으로 정의되지 않은 외부 리소스 또는 저장된 정보를 테라폼 내에서 참조하기 위해 사용합니다.
$ terraform plan && terraform apply -auto-approve
data.aws_ami.ubuntu: Reading...
data.aws_ami.ubuntu: Read complete after 0s [id=ami-07d1d85660ec58cd3]
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
$ terraform console
> data.aws_ami.ubuntu.id
"ami-07d1d85660ec58cd3"
Step3. Cloud-init Script 작성
Cloud-init 은 클라우드 환경에서 인스턴스(VM)를 프로비저닝할 때 호스트 이름, 네트워크 인터페이스, 인증키 설정 등의 초기 설정과 각 인스턴스의 구성 어플리케이션 설치를 자동화하는 도구입니다.
테라폼으로 인스턴스를 프로비저닝하는 경우, Cloud-init 을 사용함으로써 각 인스턴스에 필요한 어플리케이션과 해당 종속성을 자동으로 설치 및 구성하여 시간을 절약하고 대규모로 유지 관리할 수 있습니다.
Cloud-init 은 대부분의 리눅스 배포판과 주요 클라우드 제공업체에서 사용이 가능한 표준 구성 지원 도구입니다.
여기서는 패스워드 없이 인스턴스에 접속하도록 하는 SSH 인증키 설정과 Apache 웹 서버 설치 구성을 스크립트 형식으로 user_data에 넣어 전달할 것입니다.
- 로컬 SSH 인증키 생성
로컬 터미널에서 인스턴스에 접속할 SSH 인증키를 생성합니다.
키 생성 명령어 인자 값으로 이메일 주소를 입력하고 패스워드 문자열은 공란으로 넘어갑니다.
$ ssh-keygen -t rsa -C "okms1017@gmail.com" -f ./tf-cloud-init
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in ./tf-cloud-init
Your public key has been saved in ./tf-cloud-init.pub
The key fingerprint is:
SHA256:xYSERep1i72r9ANukd+U6UlZoxsNohymbKMmbmDphqk okms1017@gmail.com
The key's randomart image is:
+---[RSA 3072]----+
| =+.. |
| ...o |
| . . + |
| . .o=... o |
| . ..+S+o. O . |
|.o = * .O . |
|+o o o.+.= + |
|ooo o .o.o.= |
|Eo.o ...o. |
+----[SHA256]-----+
명령어 실행 이후 'tf-cloud-init'와 'tf-cloud-init.pub' 2개의 파일이 생성된 것을 확인합니다.
- Cloud-init Script 작성
scripts 디렉토리를 생성하고 하위 경로에 'add-ssh-apache.yaml' 스크립트 파일을 작성합니다.
- groups : ubuntu, devops 그룹을 생성하고 ubuntu 그룹에 root, sys 시스템 계정을 포함합니다
- users : 패스워드 없이 접속이 가능하고 관리자 권한의 명령어를 수행할 수 있는 시스템 계정을 생성합니다
- users[1].ssh_authorized_keys : 로컬에서 생성한 SSH 공개키를 입력합니다
- packages : 어플리케이션 패키지를 다운로드하고 실행합니다. ex) apache2
- runcmd : 인스턴스 부팅 이후 수행할 명령어를 입력합니다. Apache 메인 페이지 문구를 변경합니다.
Step4. 테라폼 구성파일 작성
EC2 웹 서버를 배포하기 위한 테라폼 구성파일을 작성합니다.
구성파일(*.tf)은 테라폼과 프로바이더 버전을 명시한 terraform.tf 파일, 데이터 소스와 리소스를 정의한 main.tf 파일, 변수 값을 전달하는 variables.tf 파일로 구성됩니다.
그리고 user_data를 전달하기 위한 add-ssh-apache.yaml 파일이 있습니다.
./deploy/
├── instance
│ ├── main.tf
│ ├── terraform.tf
│ └── variables.tf
└── scripts
└── add-ssh-apache.yaml
1) terraform.tf : 테라폼과 프로바이더(aws) 버전 명시
- terraform.required_providers.aws.version : 프로바이더(aws) 버전은 v5.47.0을 포함한 v5.47.x을 허용하나, v5.x는 허용하지 않음
- terraform.required_version : 테라폼 버전은 v1.1을 포함한 v1.x를 허용하나, v2.0 이상은 허용하지 않음
2) main.tf : 데이터 소스와 리소스, Output 블록 정의
- var.region : variables.tf 파일에서 선언한 region 변수 값 (ap-northeast-2)
- data.aws_ami.ubuntu : 'name'과 'virtualization-type'으로 필터링하여 가장 최신의 Ubuntu AMI 이미지를 가져옴
- data.aws_vpc.default-vpc : vpc 태그 값으로 필터링하여 기본 디폴트 VPC 정보를 가져옴
- data.aws_subnet.default-subnet : subnet 태그 값으로 필터링하여 기본 Subnet 정보를 가져옴
- aws_security_group.web_sg : 신규 웹 서버에 연결할 보안 그룹
- aws_security_group_rule.sg_22 : 신규 웹 서버에 접속(SSH)하기 위한 22(inbound) 보안 그룹
- aws_security_group_rule.sg_80 : 신규 웹 서비스(HTTP)를 위한 80(inbound) 보안 그룹
- aws_security_group_rule.sg_00 : 웹 서버에 대한 Any(Outbound) 보안 그룹
- sg 보안그룹 규칙은 추가·삭제·변경을 고려하여 별도 리소스 블록으로 분리 선언함
- aws_instance.web : 디폴트 VPC/Subnet 정보와 AMI 이미지를 받아 보안그룹, user_data 정보와 함께 생성되는 인스턴스 리소스
- output.public_ip : 리소스 프로비저닝 이후 할당되는 속성 값(public ip)을 화면 또는 파일로 출력함
3) variables.tf : 변수 선언
- variable.region.description : region 변수의 부연 설명
- variable.region.default : region 변수의 실제 값으로, 리전명이 기입됨 ex) ap-northeast-2, us-east-1
Step5. EC2 웹 서버 배포 및 접속 테스트
작업 공간을 초기화합니다.
$ terraform init
./.terraform
└── providers
└── registry.terraform.io
└── hashicorp
└── aws
└── 5.47.0
└── linux_amd64
└── terraform-provider-aws_v5.47.0_x5
구성파일 작성을 완료하면 실행계획을 생성하고 이상이 없을 시 EC2 웹 서버를 배포합니다.
$ terraform plan && terraform apply -auto-approve
aws_security_group.sg_80: Creation complete after 1s [id=sg-097fb967c94d7b31f]
aws_security_group.sg_22: Creation complete after 2s [id=sg-0e5f40e72878481c1]
aws_instance.web: Creation complete after 12s [id=i-03ff38cb92ce3af40]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
서버가 배포되고 어플리케이션이 실행되기까지 약 3분 정도가 소요됩니다.
지정한 default-subnet01(172.31.0.0/24) 네트워크 대역에 서버(172.31.1.57/32)가 배포되고, 외부 접속이 가능한 공인 IP(43.200.7.34/32)를 할당받았습니다.
- SSH 접속 테스트
로컬에서 해당 웹 서버로 패스워드 없이 SSH 접속을 시도합니다.
새로 생성한 계정(okms1017)으로 정상 접속이 되고 있습니다.
$ terraform output -raw public_ip
43.200.7.34
$ ssh okms1017@$(terraform output -raw public_ip) -i ./tf-cloud-init
Welcome to Ubuntu 24.04 LTS (GNU/Linux 6.8.0-1009-aws x86_64)
IPv4 address for ens5: 172.31.1.57
- WEB 서비스 테스트
Apache 서비스 또한 user_data로 전달한 문구가 정상적으로 출력되는 모습입니다.
$ while true; do curl --connect-timeout 1 http://43.200.7.34:80/ ; echo "------------------------------"; date; sleep 1; done
Sun Jun 15 :16:26 KST 2024
Welcome to Seong's Skill Builder!
실습을 완료하고 리소스를 반납합니다.
$ terraform destroy -auto-approve
[출처]
1) https://developer.hashicorp.com/terraform/tutorials/provision/cloud-init
2) https://cloudinit.readthedocs.io/en/latest/reference/examples.html
'IaC > Terraform' 카테고리의 다른 글
[Terraform] 3-1. For each와 Map을 활용하여 리소스 관리하기 (0) | 2024.06.30 |
---|---|
[Terraform] 2-3. Count 장애 상황 재현하기 (0) | 2024.06.23 |
[Terraform] 2-2. Count 활용과 제약사항 (0) | 2024.06.23 |
[Terraform] 2-1. EC2 웹 서버 커스터마이징하기 (0) | 2024.06.22 |
[Terraform] 1-1. Cloud Shell을 이용하여 테라폼 실행하기 (0) | 2024.06.16 |