검증
스모크 테스트
섹션 제목: “스모크 테스트”cloud-init 완료를 위해 5~10분 대기 후 아래 확인을 실행합니다.
헬스 엔드포인트
섹션 제목: “헬스 엔드포인트”ORIGIN_IP=$(terraform output -raw public_ip)
curl -sf "http://${ORIGIN_IP}/health" | jq .예상 결과:
{ "status": "healthy", "component": "origin-server", "applications": ["juice-shop", "dvwa", "vampi", "httpbin", "whoami", "csd-demo", "dvga", "restaurant", "crapi"]}애플리케이션 엔드포인트
섹션 제목: “애플리케이션 엔드포인트”# 기본 랜딩 페이지curl -sf "http://${ORIGIN_IP}/" -o /dev/null -w "Landing: %{http_code}\n"
# Juice Shopcurl -sf "http://${ORIGIN_IP}/juice-shop/" -o /dev/null -w "Juice Shop: %{http_code}\n"
# DVWAcurl -sf "http://${ORIGIN_IP}/dvwa/" -o /dev/null -w "DVWA: %{http_code}\n"
# VAmPIcurl -sf "http://${ORIGIN_IP}/vampi/" -o /dev/null -w "VAmPI: %{http_code}\n"
# httpbincurl -sf "http://${ORIGIN_IP}/httpbin/get" -o /dev/null -w "httpbin: %{http_code}\n"
# whoamicurl -sf "http://${ORIGIN_IP}/whoami/" -o /dev/null -w "whoami: %{http_code}\n"
# DVGAcurl -sf "http://${ORIGIN_IP}/dvga/" -o /dev/null -w "DVGA: %{http_code}\n"
# RESTaurantcurl -sf "http://${ORIGIN_IP}/restaurant/docs" -o /dev/null -w "RESTaurant: %{http_code}\n"
# crAPI (포트 8888)curl -sf "http://${ORIGIN_IP}:8888" -o /dev/null -w "crAPI: %{http_code}\n"모두 200을 반환해야 합니다 (DVWA는 로그인 페이지로 302 리다이렉트 반환).
자동화된 스모크 테스트
섹션 제목: “자동화된 스모크 테스트”레포지토리에는 39개 항목으로 구성된 스모크 테스트 스위트가 포함되어 있습니다:
./tests/smoke-test.sh ${ORIGIN_IP}이 테스트는 9개 애플리케이션 전체, 헬스 엔드포인트, VAmPI 등록/로그인, CSD Demo 데이터 유출 왕복 테스트, DVGA GraphQL, RESTaurant Swagger, 포트 8888의 crAPI, nginx gzip 및 버전 숨김을 검증합니다.
Docker 컨테이너 상태
섹션 제목: “Docker 컨테이너 상태”VM에 SSH로 접속하여 41개 컨테이너가 모두 실행 중인지 확인합니다:
ssh azureuser@${ORIGIN_IP} "sudo docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'" | sort예상 출력 (41개 컨테이너):
NAMES STATUS PORTScrapi-community Up X minutescrapi-identity Up X minutescrapi-mailhog Up X minutes 0.0.0.0:18025->8025/tcpcrapi-mongo Up X minutes 27017/tcpcrapi-postgres Up X minutes 5432/tcpcrapi-web Up X minutes 0.0.0.0:8888->80/tcpcrapi-workshop Up X minutescsd-demo-1 Up X minutes 127.0.0.1:5001->5001/tcpcsd-demo-2 Up X minutes 127.0.0.1:5002->5001/tcpcsd-demo-3 Up X minutes 127.0.0.1:5003->5001/tcpcsd-demo-4 Up X minutes 127.0.0.1:5004->5001/tcpdvga-1 Up X minutes 127.0.0.1:5201->5013/tcpdvga-2 Up X minutes 127.0.0.1:5202->5013/tcpdvga-3 Up X minutes 127.0.0.1:5203->5013/tcpdvga-4 Up X minutes 127.0.0.1:5204->5013/tcpdvwa-1 Up X minutes 127.0.0.1:8101->80/tcpdvwa-2 Up X minutes 127.0.0.1:8102->80/tcpdvwa-3 Up X minutes 127.0.0.1:8103->80/tcpdvwa-4 Up X minutes 127.0.0.1:8104->80/tcpdvwa-db Up X minutes 3306/tcphttpbin-1 Up X minutes 127.0.0.1:8201->80/tcphttpbin-2 Up X minutes 127.0.0.1:8202->80/tcphttpbin-3 Up X minutes 127.0.0.1:8203->80/tcphttpbin-4 Up X minutes 127.0.0.1:8204->80/tcpjuice-shop-1 Up X minutes 127.0.0.1:3001->3000/tcpjuice-shop-2 Up X minutes 127.0.0.1:3002->3000/tcpjuice-shop-3 Up X minutes 127.0.0.1:3003->3000/tcpjuice-shop-4 Up X minutes 127.0.0.1:3004->3000/tcprestaurant-1 Up X minutes 127.0.0.1:8301->8080/tcprestaurant-2 Up X minutes 127.0.0.1:8302->8080/tcprestaurant-3 Up X minutes 127.0.0.1:8303->8080/tcprestaurant-4 Up X minutes 127.0.0.1:8304->8080/tcprestaurant-db Up X minutes 5432/tcpvampi-1 Up X minutes 127.0.0.1:5101->5000/tcpvampi-2 Up X minutes 127.0.0.1:5102->5000/tcpvampi-3 Up X minutes 127.0.0.1:5103->5000/tcpvampi-4 Up X minutes 127.0.0.1:5104->5000/tcpwhoami-1 Up X minutes 127.0.0.1:8082->80/tcpwhoami-2 Up X minutes 127.0.0.1:8083->80/tcpwhoami-3 Up X minutes 127.0.0.1:8084->80/tcpwhoami-4 Up X minutes 127.0.0.1:8085->80/tcpnginx 상태
섹션 제목: “nginx 상태”ssh azureuser@${ORIGIN_IP} "sudo nginx -t && sudo systemctl status nginx --no-pager"문제 해결
섹션 제목: “문제 해결”cloud-init이 아직 실행 중인 경우
섹션 제목: “cloud-init이 아직 실행 중인 경우”엔드포인트가 502 또는 연결 거부를 반환하는 경우, cloud-init이 아직 프로비저닝 중일 수 있습니다:
ssh azureuser@${ORIGIN_IP} "cloud-init status"status: running— 아직 프로비저닝 중, 몇 분 대기status: done— 프로비저닝 완료, Docker 컨테이너 확인status: error— 아래 로그 확인
cloud-init 로그
섹션 제목: “cloud-init 로그”ssh azureuser@${ORIGIN_IP} "sudo tail -100 /var/log/cloud-init-output.log"컨테이너가 시작되지 않는 경우
섹션 제목: “컨테이너가 시작되지 않는 경우”# 컨테이너 로그 확인 (각 앱은 -1부터 -4까지 4개 인스턴스를 가짐)ssh azureuser@${ORIGIN_IP} "sudo docker logs juice-shop-1 2>&1 | tail -20"ssh azureuser@${ORIGIN_IP} "sudo docker logs dvwa-1 2>&1 | tail -20"ssh azureuser@${ORIGIN_IP} "sudo docker logs vampi-1 2>&1 | tail -20"ssh azureuser@${ORIGIN_IP} "sudo docker logs httpbin-1 2>&1 | tail -20"ssh azureuser@${ORIGIN_IP} "sudo docker logs csd-demo-1 2>&1 | tail -20"ssh azureuser@${ORIGIN_IP} "sudo docker logs dvga-1 2>&1 | tail -20"ssh azureuser@${ORIGIN_IP} "sudo docker logs restaurant-1 2>&1 | tail -20"ssh azureuser@${ORIGIN_IP} "sudo docker logs crapi-web 2>&1 | tail -20"nginx가 502를 반환하는 경우
섹션 제목: “nginx가 502를 반환하는 경우”업스트림 컨테이너가 준비되지 않았거나 충돌한 상태입니다:
# nginx 오류 로그 확인ssh azureuser@${ORIGIN_IP} "sudo tail -20 /var/log/nginx/error.log"
# 특정 앱의 모든 인스턴스 재시작ssh azureuser@${ORIGIN_IP} "for i in 1 2 3 4; do sudo docker restart juice-shop-\$i; done"
# 모든 컨테이너 재빌드 및 재시작ssh azureuser@${ORIGIN_IP} "cd /opt/origin-server && sudo docker compose build && sudo docker compose up -d"디스크 공간
섹션 제목: “디스크 공간”Docker 이미지는 약 4.7GiB를 소비합니다. CDN 부하 테스트 중 디스크 고갈을 방지하기 위해 액세스 로깅이 비활성화되어 있습니다. Logrotate는 심층 방어 수단으로 구성되어 있습니다 (500MiB 제한). 디스크 사용량 확인:
ssh azureuser@${ORIGIN_IP} "df -h / && sudo docker system df"컨테이너 메모리
섹션 제목: “컨테이너 메모리”메모리 한도에 근접한 컨테이너 확인 (OOM 위험):
ssh azureuser@${ORIGIN_IP} "sudo docker stats --no-stream --format 'table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}' | sort"모든 서비스 재시작
섹션 제목: “모든 서비스 재시작”필요한 경우 모든 서비스를 재빌드하고 재시작합니다:
ssh azureuser@${ORIGIN_IP} "cd /opt/origin-server && sudo docker compose down && sudo docker compose build && sudo docker compose up -d && sudo systemctl restart nginx"