테라폼에서 AWS와 연동하기 위해서 사용할 IAM 사용자를 AdministratorAccess 정책을 연동하여 생성해줍니다.
생성한 IAM 사용자에서 access key와 secret access key를 발급한 후 잘 저장해줍니다.
테라폼에서 사용할 tf 파일에 IAM key들이 노출이 되면 안되기 때문에 aws configure를 이용해 민감한 정보를 로컬에서 받아올 수 있게
$ aws configure
명령어로 aws key를 등록해줍니다.
aws-cli 설치 문서
https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html
ec2.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "cicd" {
ami = "ami-03221589fd7c8f183"
instance_type = "t2.micro"
key_name = aws_key_pair.cicd_make_keypair.key_name
vpc_security_group_ids = [aws_security_group.cicd_sg.id]
associate_public_ip_address = true
tags = {
Name = "cicd"
}
}
EC2를 생성할 수 있는 tf파일 입니다.
resource "tls_private_key" "cicd_make_key" {
algorithm = "RSA"
rsa_bits = 4096
}
resource "aws_key_pair" "cicd_make_keypair" {
key_name = "cicd_key"
public_key = tls_private_key.cicd_make_key.public_key_openssh
}
resource "local_file" "cicd_downloads_key" {
filename = "cicd_key.pem"
content = tls_private_key.cicd_make_key.private_key_pem
}
tls_private_key 리소스를 사용하여 "cicd_make_key" 라는 이름의 RSA 알고리즘 및 2048 비트의 개인 키를 생성합니다.
이렇게 생성된 개인 키는 tls_private_key.cicd_make_key.private_key_pem 값으로 참조할 수 있습니다.
aws_key_pair 리소스를 사용하여 AWS EC2 Key Pair를 생성합니다.
tls_private_key 단계에서 생성된 개인 키를 사용하여 공개 키를 생성합니다.
이렇게 생성된 AWS EC2 Key Pair는 aws_key_pair.cicd_make_keypair.key_name 값으로 참조할 수 있습니다.
local_file 리소스를 사용하여 개인 키를 로컬 파일로 저장합니다.
aws_key_pair 단계에서 생성된 AWS EC2 Key Pair의 이름을 파일 이름으로 사용하고, 개인 키를 PEM 형식으로 인코딩하여 저장합니다.
이렇게 생성된 파일은 cicd_key.pem 파일 이름으로 저장됩니다.
resource "aws_security_group" "cicd_sg" {
name_prefix = "cicd-sg"
vpc_id = aws_vpc.cicd_vpc.id
}
resource "aws_security_group_rule" "cicd_sg_ingress_ssh" {
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["{허용할 CIDR}"]
security_group_id = aws_security_group.cicd_sg.id
}
resource "aws_security_group_rule" "cicd_sg_ingress_https" {
type = "ingress"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["{허용할 CIDR}"]
security_group_id = aws_security_group.cicd_sg.id
}
resource "aws_security_group_rule" "cicd_sg_egress_all" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["{허용할 CIDR}"]
security_group_id = aws_security_group.cicd_sg.id
}
인바운드 규칙을 포함하는 새 보안 그룹을 만들고 aws_security_group_rule 리소스를 사용하여 SSH 액세스를 허용하는 규칙을 추가합니다.
ec2.tf
vpc_security_group_ids = [aws_security_group.cicd_sg.id]
aws_instance 리소스의 vpc_security_group_ids 매개 변수를 사용하여 EC2 인스턴스가 위에서 만든 보안 그룹을 사용하도록 구성합니다.
테라폼 설치 블로그 를 참고하여 각 실행환경에 맞게 테라폼을 설치해줍니다.
상태 저장을 위한 .tfstate 파일을 생성합니다.
여기에는 가장 마지막에 적용한 테라폼 내역이 저장됩니다.
정의한 코드가 어떤 인프라를 만들게 되는지 미리 예측 결과를 보여줍니다.
terraform apply 하기 전 실행하여 결과를 예측한 뒤 실행하면 오류의 확률을 줄여줍니다.
실제로 인프라를 배포하기 위한 명령어입니다. apply를 완료하면, AWS 상에 실제로 해당 인프라가 생성되고 작업 결과가 backend의 .tfstate 파일에 저장됩니다.
해당 결과는 local의 .terraform 파일에도 저장됩니다
$ terraform apply
명령어를 실행하여 작성했던 .tf 파일들을 읽어 ec2가 생성이 됩니다.
ec2 console에 접속하여 정상적으로 인스턴스가 생성이 됐는지 확인합니다.
$ ssh -i ./cicd_key.pem ec2-user@3.34.1.167
생성했던 pem키를 이용해 ssh로 접속하여 정상적으로 인스턴스가 생성되고 작동하는지 확인하면 마무리됩니다.
resource "aws_vpc" "cicd_vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "cicd-vpc"
}
}
resource "aws_subnet" "cicd_subnet" {
cidr_block = "10.0.1.0/24"
vpc_id = aws_vpc.cicd_vpc.id
tags = {
Name = "cicd-subnet"
}
}
VPC와 Subnet을 작성해주면 해당 VPC와 Subnet이 생성됩니다.
그리고 해당 VPC를 모두 참조해야 하므로 변경해보겠습니다.
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "cicd" {
ami = "ami-03221589fd7c8f183"
instance_type = "t3.micro"
key_name = aws_key_pair.cicd_make_keypair.key_name
vpc_security_group_ids = [aws_security_group.cicd_sg.id]
subnet_id = aws_subnet.cicd_subnet.id
# availability_zone = "ap-northeast-2a"
associate_public_ip_address = true
tags = {
Name = "cicd"
}
}
Subnet으로 묶을 인스턴스에 subnet_id = aws_subnet.cicd_subnet.id
속성을 추가해줍니다.
resource "aws_instance" "application" {
ami = "ami-03221589fd7c8f183"
instance_type = "t3.micro"
key_name = aws_key_pair.cicd_make_keypair.key_name
vpc_security_group_ids = [aws_security_group.cicd_sg.id]
subnet_id = aws_subnet.cicd_subnet.id
# availability_zone = "ap-northeast-2a"
tags = {
Name = "application"
}
}
Subnet으로 묶을 인스턴스에 subnet_id = aws_subnet.cicd_subnet.id
속성을 추가해서 새로운 인스턴스 resource를 작성해줍니다.
resource "aws_security_group" "cicd_sg" {
name_prefix = "cicd-sg"
vpc_id = aws_vpc.cicd_vpc.id
}
보안그룹에도 vpc_id = aws_vpc.cicd_vpc.id
를 참조해줍니다.
resource "aws_internet_gateway" "cicd_igw" {
vpc_id = aws_vpc.cicd_vpc.id
tags = {
Name = "cicd-igw"
}
}
resource "aws_route_table" "cicd_rt" {
vpc_id = aws_vpc.cicd_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.cicd_igw.id
}
tags = {
Name = "cicd-rt"
}
}
resource "aws_route_table_association" "cicd_rta" {
subnet_id = aws_subnet.cicd_subnet.id
route_table_id = aws_route_table.cicd_rt.id
}
Subnet으로 따로 묶었기 때문에 ssh 접속 등 되지 않습니다.
vpc_id = aws_vpc.cicd_vpc.id
VPC 또한 참조해줍니다.
aws_internet_gateway 리소스는 인터넷 게이트웨이를 생성하고
aws_route_table 리소스는 VPC의 라우팅 테이블을 업데이트합니다. 마지막으로 aws_route_table_association 리소스는 서브넷과 라우팅 테이블을 연결합니다.
resource "aws_security_group_rule" "cicd_sg_ingress_internal" {
type = "ingress"
from_port = 0
to_port = 0
protocol = "-1"
source_security_group_id = aws_security_group.cicd_sg.id
security_group_id = aws_security_group.cicd_sg.id
}
해당 보안그룹은 같은 보안 그룹에 속한 인스턴스끼리는 모든 포트에 대해 서로 통신이 가능하게 해줍니다.
github code : https://github.com/salgu1998/cicd
reference :