문제상황
프라이빗 서브넷을 사용한 인스턴스에서 nginx aws cli 등등 패키지를 다운받아야 하는 상황인데 NAT가 안 붙어있는데 어떻게 해결해야할 것인가?
시행착오
처음에는 ec2 인스턴스를 만들 때 Userdata에 스크립트를 넣어서 인스턴스를 만들면 될 줄 알았는데, 이것또한 NAT가 없으니 프로비저닝이 되지 않았습니다.
해결방법
packer를 사용해서 프로비저닝 된 AMI를 만들어서 해결합니다!
MAC Packer 설치 가이드
https://developer.hashicorp.com/packer/tutorials/docker-get-started/get-started-install-cli
brew tap hashicorp/tap
Hashicorp tap 을 다운받아야 합니다. 그에 대한 명령어
brew install hashicorp/tap/packer
packer를 hashicorp/tap/packer를 사용해서 설치합니다.
packer
설치 되었는지는, packer 명령으로 확인할 수 있어요!
이제 제가 만들어볼까요!
디렉토리 구조입니다.
install-aws-cli.sh
이 스크립트 파일은 우분투 환경에서 AWS Cli설치, Credential 설정, 그리고 nginx설치와 config파일 입력까지 포함합니다.
#!/bin/bash
# AWS CLI 설치
sudo apt-get update -y
sudo apt-get install -y nginx python3-pip# Install AWS CLI using pip
sudo pip3 install awscli# AWS Credential 설정
mkdir -p /home/ubuntu/.aws
cat > /home/ubuntu/.aws/credentials <<EOL
[default]
aws_access_key_id = ${AWS_ACCESS_KEY}
aws_secret_access_key = ${AWS_SECRET_KEY}
EOLcat > /home/ubuntu/.aws/config <<EOL
[default]
region = ${AWS_REGION}
EOL# 설정 파일의 소유권 변경
sudo chown -R ubuntu:ubuntu /home/ubuntu/.awsecho "AWS_ACCESS_KEY: $AWS_ACCESS_KEY"
echo "AWS_SECRET_KEY: $AWS_SECRET_KEY"
echo "AWS_REGION: $AWS_REGION"# Configure nginx
sudo bash -c "cat > /etc/nginx/nginx.conf" <<'EOL'
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;events {
worker_connections 768;
# multi_accept on;
}http { ##
# Basic Settings
## sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off; # server_names_hash_bucket_size 64;
# server_name_in_redirect off; include /etc/nginx/mime.types;
default_type application/octet-stream; ##
# SSL Settings
## #ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
#ssl_prefer_server_ciphers on; ##
# Logging Settings
## access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log; ##
# Gzip Settings
## gzip on; # gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; ##
# Virtual Host Configs
## include /etc/nginx/conf.d/*.conf;
#include /etc/nginx/sites-enabled/*; ##
# Server Configs
## server {
listen 80;
server_name office.onthelook.internal; ##
# Location Configs
##
location / {
}
location /<엔드포인트1> {
alias /home/ubuntu/<경로>;
index index.html;
} location /<엔드포인트2> {
alias /home/ubuntu/<파일경로>/build;
index index.html;
} ##
# Error Pages Configs
## error_page 404 /404.html;
location = /404.html {
internal;
} ##
# Redirects Configs
## # Redirect non-www to www
if ($host !~* ^(www)) {
rewrite ^(.*)$ <http://www.$host$1> permanent;
} # Redirect HTTP to HTTPS
#if ($scheme != "https") {
# return 301 https://$server_name$request_uri;
#} ##
# SSL Configs
## #ssl_certificate /etc/ssl/certs/your_cert.crt;
#ssl_certificate_key /etc/ssl/private/your_key.key;
#ssl_session_timeout 5m;
#ssl_protocols TLSv1.1 TLSv1.2;
#ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
#ssl_prefer_server_ciphers on;
}
}EOL# Start and enable nginx
sudo systemctl start nginx
sudo systemctl enable nginx
aws-ubuntu.pkr.hcl
이 hcl 파일은 우분투 20.04 이미지를 기반으로 만들고, scripts 디렉토리안에있는 install-aws-cli.sh를 이용하여 프로비저닝합니다.
AWS credential 에 들어갈 내용들을 환경변수로 선언해주었습니다.
packer {
required_plugins {
amazon = {
version = ">= 0.0.1"
source = "github.com/hashicorp/amazon"
}
}
}
source "amazon-ebs" "ubuntu" {
ami_name = "${var.ami_prefix}-${local.timestamp}"
instance_type = "t2.micro"
region = "ap-northeast-2"
source_ami_filter {
filters = {
name = "ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = ["099720109477"]
}
ssh_username = "ubuntu"
}build {
sources = [
"source.amazon-ebs.ubuntu"
] provisioner "shell" {
script = "scripts/install-aws-cli.sh"
environment_vars = [
"AWS_ACCESS_KEY=${var.aws_access_key}",
"AWS_SECRET_KEY=${var.aws_secret_key}",
"AWS_REGION=${var.aws_region}"
]
}
}variable "ami_prefix" {
type = string
default = "private-backoffice-correct-ami"
}locals {
timestamp = regex_replace(timestamp(), "[- TZ:]", "")
}
variables.pkr.hcl
변수에 대해서 값을 넣어줍니다. variable에 값에서 default를 비워주겠습니다.
variable "aws_access_key" {
type = string
default = ""
}
variable "aws_secret_key" {
type = string
default = ""
}variable "aws_region" {
type = string
default = ""
}
variables.auto.pkvars.hcl
variables.auto.pkvars.hcl에서 디폴트에 들어갈 값들을 넣어주면 packer bulid를 할 때 그 값들이 적용되어서 들어가게됩니다.
aws_access_key = "AXXXXXXXXXXXXX"
aws_secret_key = "XXXXXXXXXXXaXXXXXXXXX"
aws_region = "ap-northeast-2"
VScode SSH 연결 config
Host private-backoffice-fixed
HostName <프라이빗 서브넷>
User ubuntu
IdentityFile /<pem키 경로>
ProxyCommand ssh -W %h:%p backoffice-bastion
이 부분은 따로 다른 페이지에서 정리해놓겠습니다.
그 후 이렇게 만들어진 프라이빗 인스턴스 안에서
aws configure list
명령을 하게 되면, variables.auto.pkvars.hcl에 넣었던 내용들이 잘 들어가서 프로비저닝되었음을 확인할 수 있다.
뿐만아니라 aws 명령어가 입력이 되는것을 확인하여서 쉘 스크립트로 userdata에 넣었던 내용들(aws 명령어)도 잘 프로비저닝되어서 들어간 것을 확인할 수 있습니다!
variables.pkr.hcl 에서 default에 값을 넣어서 프로비저닝을 할 수도 있지만, variables.auto.pkvars.hcl에 값을 넣고 사용하면서 깃이나 어딘가에 코드를 공유할 때 커밋 안하면 되니까 재사용성도 높은것같아서 packer 잘 사용하게 될 것 같습니다!