[ AWS Terraform ] NginX 리버스 프록시 설정 관련
terraform 코드에서 명시적으로 지정하려고 했는데 에러가 발생했다.
가장 쉬운 방법은 수동으로 터미널 진입해서 작성해주는건데, 일단 2차 프로젝트에서는 이렇게 진행하고, 3차에는 프로비저너 이용해서 쓰는 걸로 하자 ...
# 원본 코드
resource "aws_instance" "A_Public" {
ami = "ami-062cf18d655c0b1e8"
instance_type = "t2.medium"
subnet_id = aws_subnet.Public_A1.id
key_name = "KDT_Project2_AWS"
vpc_security_group_ids = [aws_security_group.default.id]
tags = {
Name = "A_Public"
}
user_data = <<-EOF
#!/bin/bash
# 로깅 확인 파일 생성
LOG_FILE=/var/log/user_data.log
exec > >(tee -a $LOG_FILE) 2>&1
# 호스트 이름 변경
hostnamectl set-hostname a-public
echo "127.0.1.1 a-public" >> /etc/hosts
echo "호스트 이름 변경 완료!"
# SSH 포트 변경
sed -i 's/#Port 22/Port 51228/' /etc/ssh/sshd_config
systemctl restart sshd
echo "SSH 포트 변경 성공!"
# PEM 파일 생성 및 권한 설정
echo "${var.key_pair_content}" > /home/ubuntu/KDT_Project2_AWS.pem
chmod 400 /home/ubuntu/KDT_Project2_AWS.pem
echo "키 페어 파일 생성 및 권한 설정 완료!"
# Nginx 및 OpenJDK 17 설치
sudo apt-get update
sudo apt-get install -y curl gnupg2 ca-certificates lsb-release
# ubuntu-keyring 패키지 설치
sudo apt-get install -y ubuntu-keyring
# nginx.list 파일 생성 : 공식 저장소에서 서명 키 가져오기
curl -s https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
# 다운로드한 키가 올바른지 확인
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
# 저장소 설정 (Stable version)
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
# 저장소 업데이트
sudo apt-get update
# nginx 설치
sudo apt-get install -y nginx
# nginx 버전 확인
nginx -v
# nginx 가동 시작
sudo systemctl start nginx
# OpenJDK 17 설치
sudo apt update
sudo apt install -y openjdk-17-jdk
echo "Nginx와 JDK 17 설치 완료!"
# Nginx 리버스 프록시 설정
A_PRIVATE01_IP=$(aws ec2 describe-instances --instance-ids ${aws_instance.A_Private01.id} --query "Reservations[*].Instances[*].PrivateIpAddress" --output text)
B_PRIVATE01_IP=$(aws ec2 describe-instances --instance-ids ${aws_instance.B_Private01.id} --query "Reservations[*].Instances[*].PrivateIpAddress" --output text)
sudo sed -i '/http {/a \\
upstream inclass-spring-security {\\
server ${A_PRIVATE01_IP}:8080 weight=100 max_fails=3 fail_timeout=3s;\\
server ${B_PRIVATE01_IP}:8080 weight=100 max_fails=3 fail_timeout=3s;\\
}\\
server {\\
location / {\\
proxy_pass http://inclass-spring-security;\\
proxy_http_version 1.1;\\
proxy_set_header Upgrade $http_upgrade;\\
proxy_set_header Connection "upgrade";\\
proxy_set_header Host $host;\\
proxy_cache_bypass $http_upgrade;\\
}\\
}' /etc/nginx/nginx.conf
sudo systemctl restart nginx
echo "Nginx 리버스 프록시 설정 완료!"
EOF
}
resource "aws_eip" "a_public_eip" {
instance = aws_instance.A_Public.id
vpc = true
}
이 코드에서 수정 진행, 2차 플젝은 저기서 nginx 리버스 프록시 설정하는 버전 지우고, 수동으로 설정해줌
에러 코드 :
Error: Invalid reference
│
│ on ec2_instances.tf line 167, in resource "aws_instance" "A_Public":
│ 167: server ${A_PRIVATE01_IP}:8080 weight=100 max_fails=3 fail_timeout=3s;\\
│
│ A reference to a resource type must be followed by at least one attribute access, specifying the resource name.
╵
╷
│ Error: Invalid reference
│
│ on ec2_instances.tf line 168, in resource "aws_instance" "A_Public":
│ 168: server ${B_PRIVATE01_IP}:8080 weight=100 max_fails=3 fail_timeout=3s;\\
│
│ A reference to a resource type must be followed by at least one attribute access, specifying the resource name.
GPT의 대답 :
Terraform에서 인스턴스의 Private IP를 가져오기 위해서는 데이터 소스를 사용해야 합니다. aws_instance 리소스가 생성된 후에 IP 주소를 사용할 수 있기 때문에, user_data에서 바로 사용할 수 없습니다.
해결 방법:
local-exec 프로비저너를 사용하여 인스턴스 생성 후 IP 주소를 가져오고, 필요한 파일을 구성합니다. Terraform에서 변수와 데이터 소스를 사용하여 이를 수행할 수 있습니다.
1. 인스턴스 정의 수정
먼저, aws_instance 리소스 정의에서 user_data를 단순화하고, 이후에 local-exec 프로비저너를 사용하여 Nginx 설정을 구성합니다.
resource "aws_instance" "A_Public" {
ami = "ami-062cf18d655c0b1e8"
instance_type = "t2.medium"
subnet_id = aws_subnet.Public_A1.id
key_name = "KDT_Project2_AWS"
vpc_security_group_ids = [aws_security_group.default.id]
tags = {
Name = "A_Public"
}
user_data = <<-EOF
#!/bin/bash
# 로깅 확인 파일 생성
LOG_FILE=/var/log/user_data.log
exec > >(tee -a $LOG_FILE) 2>&1
# 호스트 이름 변경
hostnamectl set-hostname a-public
echo "127.0.1.1 a-public" >> /etc/hosts
echo "호스트 이름 변경 완료!"
# SSH 포트 변경
sed -i 's/#Port 22/Port 51228/' /etc/ssh/sshd_config
systemctl restart sshd
echo "SSH 포트 변경 성공!"
# PEM 파일 생성 및 권한 설정
echo "${var.key_pair_content}" > /home/ubuntu/KDT_Project2_AWS.pem
chmod 400 /home/ubuntu/KDT_Project2_AWS.pem
echo "키 페어 파일 생성 및 권한 설정 완료!"
# Nginx 및 OpenJDK 17 설치
sudo apt-get update
sudo apt-get install -y curl gnupg2 ca-certificates lsb-release
# ubuntu-keyring 패키지 설치
sudo apt-get install -y ubuntu-keyring
# nginx.list 파일 생성 : 공식 저장소에서 서명 키 가져오기
curl -s https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
# 다운로드한 키가 올바른지 확인
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
# 저장소 설정 (Stable version)
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
# 저장소 업데이트
sudo apt-get update
# nginx 설치
sudo apt-get install -y nginx
# nginx 버전 확인
nginx -v
# nginx 가동 시작
sudo systemctl start nginx
# OpenJDK 17 설치
sudo apt update
sudo apt install -y openjdk-17-jdk
echo "Nginx와 JDK 17 설치 완료!"
EOF
provisioner "local-exec" {
command = <<-EOF
A_PRIVATE01_IP=$(aws ec2 describe-instances --instance-ids ${aws_instance.A_Private01.id} --query "Reservations[*].Instances[*].PrivateIpAddress" --output text)
B_PRIVATE01_IP=$(aws ec2 describe-instances --instance-ids ${aws_instance.B_Private01.id} --query "Reservations[*].Instances[*].PrivateIpAddress" --output text)
ssh -i /path/to/your/private/key ubuntu@${self.public_ip} << 'EOC'
sudo sed -i '/http {/a \\
upstream inclass-spring-security {\\
server ${A_PRIVATE01_IP}:8080 weight=100 max_fails=3 fail_timeout=3s;\\
server ${B_PRIVATE01_IP}:8080 weight=100 max_fails=3 fail_timeout=3s;\\
}\\
server {\\
location / {\\
proxy_pass http://inclass-spring-security;\\
proxy_http_version 1.1;\\
proxy_set_header Upgrade $http_upgrade;\\
proxy_set_header Connection "upgrade";\\
proxy_set_header Host $host;\\
proxy_cache_bypass $http_upgrade;\\
}\\
}' /etc/nginx/nginx.conf
sudo systemctl restart nginx
EOC
EOF
}
}
resource "aws_eip" "a_public_eip" {
instance = aws_instance.A_Public.id
vpc = true
}
2. 데이터 소스를 사용하여 인스턴스 정보 가져오기
인스턴스 생성 후에 Private IP 주소를 가져오는 방법을 추가합니다.
data "aws_instance" "A_Private01" {
instance_id = aws_instance.A_Private01.id
}
data "aws_instance" "B_Private01" {
instance_id = aws_instance.B_Private01.id
}
이제 local-exec 프로비저너에서 data 블록을 사용하여 인스턴스의 Private IP 주소를 가져올 수 있습니다.
3. 통합된 코드
아래는 통합된 코드입니다.
provider "aws" {
region = "us-west-2"
}
resource "aws_vpc" "KDT_Project2" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "Public_A1" {
vpc_id = aws_vpc.KDT_Project2.id
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
}
resource "aws_security_group" "default" {
vpc_id = aws_vpc.KDT_Project2.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 51228
to_port = 51228
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 = {
Name = "default"
}
}
resource "aws_instance" "A_Public" {
ami = "ami-062cf18d655c0b1e8"
instance_type = "t2.medium"
subnet_id = aws_subnet.Public_A1.id
key_name = "KDT_Project2_AWS"
vpc_security_group_ids = [aws_security_group.default.id]
tags = {
Name = "A_Public"
}
user_data = <<-EOF
#!/bin/bash
# 로깅 확인 파일 생성
LOG_FILE=/var/log/user_data.log
exec > >(tee -a $LOG_FILE) 2>&1
# 호스트 이름 변경
hostnamectl set-hostname a-public
echo "127.0.1.1 a-public" >> /etc/hosts
echo "호스트 이름 변경 완료!"
# SSH 포트 변경
sed -i 's/#Port 22/Port 51228/' /etc/ssh/sshd_config
systemctl restart sshd
echo "SSH 포트 변경 성공!"
# PEM 파일 생성 및 권한 설정
echo "${var.key_pair_content}" > /home/ubuntu/KDT_Project2_AWS.pem
chmod 400 /home/ubuntu/KDT_Project2_AWS.pem
echo "키 페어 파일 생성 및 권한 설정 완료!"
# Nginx 및 OpenJDK 17 설치
sudo apt-get update
sudo apt-get install -y curl gnupg2 ca-certificates lsb-release
# ubuntu-keyring 패키지 설치
sudo apt-get install -y ubuntu-keyring
# nginx.list 파일 생성 : 공식 저장소에서 서명 키 가져오기
curl -s https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
# 다운로드한 키가 올바른지 확인
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
# 저장소 설정 (Stable version)
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
# 저장소 업데이트
sudo apt-get update
# nginx 설치
sudo apt-get install -y nginx
# nginx 버전 확인
nginx -v
# nginx 가동 시작
sudo systemctl start nginx
# OpenJDK 17 설치
sudo apt update
sudo apt install -y openjdk-17-jdk
echo "Nginx와 JDK 17 설치 완료!"
EOF
provisioner "local-exec" {
command = <<-EOF
A_PRIVATE01_IP=$(aws ec2 describe-instances --instance-ids ${aws_instance.A_Private01.id} --query "Reservations[*].Instances[*].PrivateIpAddress" --output text)
B_PRIVATE01_IP=$(aws ec2 describe-instances --instance-ids ${aws_instance.B_Private01.id} --query "Reservations[*].Instances[*].PrivateIpAddress" --output text)
ssh -i /path/to/your/private/key ubuntu@${self.public_ip} << 'EOC'
sudo sed -i '/http {/a \\
upstream inclass-spring-security {\\
server ${A_PRIVATE01_IP}:8080 weight=100 max_fails=3 fail_timeout=3s;\\
server ${B_PRIVATE01_IP}:8080 weight=100 max_fails=3 fail_timeout=3s;\\
}\\
server {\\
location / {\\
proxy_pass http://inclass-spring-security;\\
proxy_http_version 1.1;\\
proxy_set_header Upgrade $http_upgrade;\\
proxy_set_header Connection "upgrade";\\
proxy_set_header Host $host;\\
proxy_cache_bypass $http_upgrade;\\
}\\
}' /etc/nginx/nginx.conf
sudo systemctl restart nginx
EOC
EOF
}
}
resource "aws_eip" "a_public_eip" {
instance = aws_instance.A_Public.id
vpc = true
}
data "aws_instance" "A_Private01" {
instance_id = aws_instance.A_Private01.id
}
data "aws_instance" "B_Private01" {
instance_id = aws_instance.B_Private01.id
}
이제 aws_instance 리소스가 생성된 후에 local-exec 프로비저너를 사용하여 인스턴스의 Private IP 주소를 가져오고, 필요한 Nginx 설정을 수행할 수 있습니다.