처음 EC2를 띄운 날. 인스턴스는 'running'인데 SSH가 계속 타임아웃입니다. 한참을 헤매다 알게 됩니다 — 보안그룹에 22번 포트를 안 열어둔 것. 다음 날엔 테스트용으로 가장 큰 타입을 골랐다가 하루 만에 몇 만 원이 나갔습니다. 가상 서버 하나에도 타입·이미지·키·방화벽이라는 네 개의 손잡이가 있고, 어느 하나만 틀려도 못 쓰거나 비싸집니다.
- 1인스턴스 타입을 패밀리·세대·크기로 읽고 워크로드에 맞출 수 있다
- 2AMI가 무엇이고 왜 반복 생성·오토스케일링의 기반인지 안다
- 3키페어로 인스턴스에 안전하게 접속하는 방식을 이해한다
- 4보안그룹(가상 방화벽)으로 접근을 통제하는 원리를 안다
- 5접속 실패·과금 같은 대표 문제의 원인을 좁힐 수 있다
가상 서버의 네 가지 손잡이
인스턴스 타입 — 워크로드에 맞는 옷을 고른다
m5.large 같은 타입은 세 부분으로 읽습니다: 패밀리(m) + 세대(5) + 크기(large).
- t: 버스트형 범용(평소 적게, 잠깐 폭증) — 개발·소규모 웹에 저렴
- m: 균형 범용(CPU:메모리 균형) — 일반 서버
- c: 컴퓨트 최적(CPU↑) — 연산·인코딩
- r: 메모리 최적(RAM↑) — 캐시·인메모리 DB
워크로드 성향과 안 맞는 타입을 고르면 비싸거나 느립니다. CPU를 갈아 넣는 작업에 메모리 최적(r)을 쓰는 건 낭비입니다.
AMI·키페어·보안그룹 — 이미지·열쇠·방화벽
AMI는 인스턴스의 디스크 템플릿입니다. OS와 미리 설치된 소프트웨어가 담겨 있어, 같은 AMI로 동일한 서버를 반복 생성할 수 있습니다. 이게 오토스케일링([[autoscaling-lb]])의 전제입니다.
키페어는 SSH 접속용 공개키/개인키 쌍입니다. 공개키는 인스턴스에 심기고, 개인키(.pem)는 내가 보관합니다. 비밀번호 대신 이 키로 신원을 증명합니다.
보안그룹은 인스턴스 앞단의 가상 방화벽입니다. "어떤 출발지에서 어떤 포트로 들어오는 것을 허용할지"를 정합니다. 기본은 전부 차단 — 명시적으로 연 것만 통합니다.

띄우고, 접속하고, 막기
공식 Amazon Linux 2023 AMI를 조회합니다. AMI는 리전마다 ID가 다르므로 코드에 ID를 박지 말고 조회하거나 SSM 파라미터를 씁니다.
aws ssm get-parameters \
--names /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 \
--query "Parameters[0].Value" --output text
ami-0abcd1234ef567890
aws ec2 describe-images모두에게 22번을 여는(0.0.0.0/0) 대신, 내 IP만 허용합니다. 공개 SSH는 즉시 봇의 무차별 대입 공격 대상이 됩니다.
MYIP=$(curl -s https://checkip.amazonaws.com)
SG=$(aws ec2 create-security-group --group-name web-sg \
--description "web" --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG" \
--protocol tcp --port 22 --cidr "${MYIP}/32"
{ "Return": true, "SecurityGroupRules": [ { "CidrIpv4": "203.0.113.5/32", "FromPort": 22 } ] }
aws ec2 authorize-security-group-ingress조회한 AMI·키페어·보안그룹으로 t3.micro 한 대를 띄웁니다.
aws ec2 run-instances \
--image-id ami-0abcd1234ef567890 \
--instance-type t3.micro \
--key-name my-key \
--security-group-ids "$SG" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=demo}]'
... "InstanceId": "i-0123456789abcdef0", "State": { "Name": "pending" } ...
aws ec2 run-instances- run-instances 직후 State가 pending→running으로 바뀌는지 — running이어야 접속 시도 가능
- 보안그룹 인바운드 규칙에 0.0.0.0/0 + 22(SSH)나 + 3389(RDP)가 있는지 — 있으면 전 세계에 관리 포트 개방. 즉시 내 IP/32로 축소
- 인스턴스에 태그(Name 등)가 붙어 있는지 — 태그 없는 자원은 나중에 '이게 뭐였지'가 되고 비용 추적도 안 됨([[cloud-cost-optimization]])
- 퍼블릭 IP가 할당됐는지 + 어떤 서브넷인지 — 접속하려면 퍼블릭 서브넷·공인 IP·라우팅이 맞아야 함
상황: 인스턴스는 running인데 SSH가 타임아웃(거부가 아니라 무응답).
원인: 거의 항상 네트워크 접근 통제. ① 보안그룹 인바운드에 내 IP의 22번이 없음, ② 인스턴스가 프라이빗 서브넷이거나 공인 IP가 없음, ③ 서브넷 라우팅이 인터넷 게이트웨이로 안 빠짐. 'Connection refused'(즉시 거부)면 포트는 열렸으나 sshd 미동작 등 다른 문제.
진단: 보안그룹 인바운드 규칙 확인 → 인스턴스의 퍼블릭 IP·서브넷 확인 → 라우팅 테이블 확인.
해결: 보안그룹에 현재 내 IP/32 : 22 추가. 인스턴스가 인터넷에서 닿아야 하면 퍼블릭 서브넷+공인 IP+IGW 라우팅을 맞춤 — 이 구조는 [[cloud-vpc-network]]에서 자세히 다룹니다. 키 권한 오류(Permissions 0644 too open)면 chmod 400 key.pem.
실무에서 보안 감사의 단골 지적이 "0.0.0.0/0으로 열린 SSH/RDP/DB 포트" 입니다. 관리 포트는 내 IP·VPN·배스천(bastion) 경유로만 열고, 가능하면 SSH 대신 세션 매니저(키 없는 접속)를 씁니다.
또한 "인스턴스를 손으로 띄우고 손으로 설정"하는 방식(스노우플레이크 서버)은 재현이 안 돼 사고를 키웁니다. 검증된 AMI + 부팅 스크립트(user data) 또는 IaC([[cloud-iac-terraform]])로 반복 가능하게 만드는 것이 실무 표준입니다.
다음 모듈에서는 이 인스턴스를 한 대가 아니라 수요에 따라 자동으로 늘렸다 줄이고, 앞에서 트래픽을 나눠주는 오토스케일링 + 로드밸런서를 다룹니다.