diff --git a/modules/app_stack/ec2.tf b/modules/app_stack/ec2.tf index c8514ba..a9ae719 100644 --- a/modules/app_stack/ec2.tf +++ b/modules/app_stack/ec2.tf @@ -98,11 +98,40 @@ resource "null_resource" "update_nginx" { })) } + # 인스턴스가 교체되면 새 인스턴스에는 nginx 가 없으므로 설정 스크립트를 다시 실행합니다. + # triggers 대신 lifecycle 을 쓰는 이유: triggers 는 state 에 저장되어 키를 추가하는 것만으로 재실행이 발생합니다. + # 리소스 전체가 아니라 id 를 참조하는 이유: 리소스 참조는 in-place update 에도 반응하지만, + # 속성 참조는 값이 바뀔 때만 반응하므로 인스턴스 교체에만 발동합니다. + lifecycle { + replace_triggered_by = [aws_instance.api_server.id] + } + provisioner "local-exec" { interpreter = ["bash", "-c"] command = <<-EOT set -euo pipefail INSTANCE_ID='${aws_instance.api_server.id}' + + # 인스턴스가 교체된 직후에는 SSM 에이전트가 아직 등록되지 않아 + # send-command 가 InvalidInstanceId 로 즉시 실패합니다. 등록될 때까지 기다립니다. + PING_STATUS="" + SSM_ATTEMPTS=0 + while [ "$SSM_ATTEMPTS" -lt 60 ]; do + PING_STATUS=$(aws ssm describe-instance-information \ + --filters "Key=InstanceIds,Values=$INSTANCE_ID" \ + --query "InstanceInformationList[0].PingStatus" \ + --output text 2>/dev/null || echo "None") + if [ "$PING_STATUS" = "Online" ]; then + break + fi + SSM_ATTEMPTS=$((SSM_ATTEMPTS + 1)) + sleep 10 + done + if [ "$PING_STATUS" != "Online" ]; then + echo "SSM agent not registered within 600s (last status: $PING_STATUS)" >&2 + exit 1 + fi + COMMAND_ID=$(aws ssm send-command \ --instance-ids "$INSTANCE_ID" \ --document-name "AWS-RunShellScript" \ diff --git a/modules/app_stack/scripts/nginx_setup.sh.tftpl b/modules/app_stack/scripts/nginx_setup.sh.tftpl index 6bd8808..c6bfd40 100644 --- a/modules/app_stack/scripts/nginx_setup.sh.tftpl +++ b/modules/app_stack/scripts/nginx_setup.sh.tftpl @@ -118,6 +118,12 @@ server { return 444; } + # 3차 차단: 내부 전용 API 는 VPC 내부에서 app 포트로 직접 호출하므로 외부 노출을 막는다 + # DB EC2 의 백업 실패 알림은 8080/9080 직접 경로를 쓰므로 이 차단에 영향받지 않는다 + location ^~ /internal { + return 444; + } + location / { proxy_pass http://app_backend; proxy_http_version 1.1;