infra
Platform

모듈 맵

[Infra Ops] AWS 기반 인프라 운영 실무와 전환 고려사항

0 / 52 완료

펼치기
0 / 52 완료0%

인프라 운영 & SRE · 51 / 52

[Infra Ops] AWS 기반 인프라 운영 실무와 전환 고려사항

온프레미스와 클라우드 인프라 차이, AWS EC2/RDS/S3/CloudWatch 운영 기초, 클라우드 전환 시 고려사항까지

🚨INCIDENT ALERT
HIGH

온프레미스 서버를 운영하다가 팀에서 AWS로 전환하기로 결정했습니다. 그런데 AWS 콘솔을 열어보니 처음 보는 용어들이 가득합니다. EC2, Security Group, RDS, VPC, S3, CloudWatch — 온프레미스에서 내가 하던 작업들이 클라우드에서 어떻게 대응되는지, 처음엔 감이 안 잡힙니다.

이 모듈에서는 온프레미스에서 하던 인프라 작업들이 AWS에서 어떻게 대응되는지 매핑합니다. 처음 AWS를 운영하는 엔지니어가 실무에서 바로 쓸 수 있는 기본 명령어와 운영 흐름을 다룹니다.

이번 챕터에서 배울 것
  • 1온프레미스와 AWS의 책임 분리 모델 차이를 설명할 수 있다
  • 2AWS EC2 인스턴스를 SSM Session Manager로 접속하고 상태를 확인할 수 있다
  • 3Security Group 인바운드/아웃바운드 규칙을 CLI로 확인하고 설명할 수 있다
  • 4AWS RDS 접속, 파라미터 그룹, 읽기 복제본 개념을 이해할 수 있다
  • 5S3에 파일을 업로드하고 AWS CLI로 기본 조작을 수행할 수 있다
  • 6CloudWatch 메트릭과 로그 그룹으로 EC2 모니터링 기초를 수행할 수 있다

온프레미스 vs 클라우드 — 책임 범위 비교

💡개념

AWS 공동 책임 모델 — 누가 무엇을 책임지나

AWS로 전환하고 나서 OS 보안 패치를 누가 해야 하는지 몰라 6개월째 방치된 EC2 인스턴스가 있었습니다. "AWS가 다 관리해주는 거 아닌가요?"라는 오해에서 비롯된 상황입니다. 데이터센터 물리 보안과 하이퍼바이저는 AWS가 책임지지만, OS 위의 모든 것은 고객 책임입니다. 이 경계를 모르면 보안 감사에서 지적받거나 실제 침해가 발생할 때 "AWS가 왜 막지 않았나요?"라는 잘못된 질문을 하게 됩니다.

온프레미스에서 AWS로 전환할 때 가장 먼저 이해해야 할 것이 책임 분리입니다. 내가 직접 해야 하는 것과 AWS가 해주는 것을 구분해야 운영 체계를 잡을 수 있습니다.

온프레미스 vs AWS 책임 분리 (공동 책임 모델) — AWS는 데이터센터 물리 보안·하이퍼바이저까지 책임지고(of the cloud), OS·미들웨어·앱·데이터·접근제어는 고객 책임(in the cloud). EC2는 OS 패치까지 고객 몫, RDS·S3 같은 관리형은 AWS 책임 범위가 넓어짐 — 경계를 알아야 운영 누락을 막음확대

영역온프레미스AWS (EC2 기준)
물리 서버/네트워크 장비운영팀 구매·관리AWS
하이퍼바이저/가상화운영팀AWS
운영체제(OS)운영팀고객 (EC2는 고객 책임)
OS 보안 패치운영팀고객
미들웨어/런타임운영팀고객
애플리케이션개발팀개발팀
데이터 암호화운영팀고객
IAM/접근 제어운영팀고객
물리 보안 (데이터센터)운영팀 또는 IDCAWS

핵심: EC2를 쓴다고 OS 패치를 AWS가 해주는 것이 아닙니다. EC2는 가상 서버를 빌린 것이고, 그 안의 OS/미들웨어/앱은 여전히 고객 책임입니다. RDS, Lambda 같은 관리형 서비스로 올라갈수록 AWS가 더 많이 담당합니다.

AWS EC2 운영

AWS 운영 실무 한눈에 — EC2 접속(SSM Session Manager 권장 vs SSH), CloudWatch 모니터링(CPU 80% 초과·StatusCheckFailed·RDS FreeStorage 20% 미만 알람), 일상 운영 체크리스트(알람·인스턴스 상태·Security Group 감사·Cost Explorer·CloudTrail), IaC 워크플로우(코드 작성→plan→apply→State 관리→드리프트 감지)확대

💡개념

EC2 인스턴스 상태 확인과 SSM 접속

온프레미스에서 서버에 SSH로 접속하던 방식이 클라우드에서는 달라집니다. 보안 강화를 위해 22번 포트를 열지 않고 SSM Session Manager로 접속하는 것이 권장됩니다.

로컬 터미널
# EC2 인스턴스 목록과 상태 확인 (AWS CLI)
aws ec2 describe-instances \
  --query "Reservations[].Instances[].[InstanceId,State.Name,PublicIpAddress,PrivateIpAddress,Tags[?Key=='Name'].Value|[0]]" \
  --output table

# 특정 인스턴스 상세 정보
aws ec2 describe-instances --instance-ids i-1234567890abcdef0

# SSM Session Manager로 접속 (SSH 포트 불필요)
aws ssm start-session --target i-1234567890abcdef0
# → 웹 콘솔과 동일한 셸 세션 시작

# EC2 인스턴스 시작/중지/재시작
aws ec2 start-instances --instance-ids i-1234567890abcdef0
aws ec2 stop-instances --instance-ids i-1234567890abcdef0
aws ec2 reboot-instances --instance-ids i-1234567890abcdef0

EC2 내에서 기본 확인 (접속 후):

로컬 또는 서버
# 인스턴스 메타데이터 확인 (인스턴스 ID, 리전 등)
curl -s http://169.254.169.254/latest/meta-data/instance-id
curl -s http://169.254.169.254/latest/meta-data/placement/region

# 시스템 리소스 확인 (온프레미스와 동일)
top
df -h
free -h
💡개념

Security Group — 클라우드의 방화벽

새 EC2 인스턴스를 올렸는데 애플리케이션에 접속이 안 됩니다. SSH도 안 됩니다. 인스턴스 상태는 "running"인데요. Security Group에서 인바운드 규칙을 추가하지 않은 것입니다. AWS의 기본 Security Group은 모든 인바운드를 차단합니다. 온프레미스에서 방화벽 규칙을 네트워크 장비에 넣던 것과 달리, 클라우드에서는 인스턴스 단위로 붙이고 콘솔이나 CLI로 즉시 변경합니다.

Security Group은 온프레미스 방화벽과 역할은 같지만 동작 방식이 다릅니다. 인스턴스 단위로 붙이고, API로 즉시 변경이 가능합니다.

Security Group 레이어 분리와 SG 참조 체이닝 — 인터넷(0.0.0.0/0)은 ALB Security Group에 80·443만, ALB-SG는 EC2 Security Group에 80·443을 소스=ALB-SG로, EC2-SG는 RDS Security Group에 3306을 소스=EC2-SG로 허용해 단계별로 잠근다. 기본 SG는 모든 인바운드를 전면 차단(default deny)하므로 running인데 접속이 안 되면 SG 인바운드부터 확인한다. SG는 stateful이라 인바운드 허용 연결의 응답 아웃바운드는 규칙 없이 통과한다. 소스를 CIDR이 아니라 다른 SG로 지정하면 DB의 IP를 알아도 EC2 SG 밖 서버에서는 3306에 닿지 못하고 오토스케일에도 자동으로 맞는다확대

로컬 터미널
# Security Group 목록 확인
aws ec2 describe-security-groups --group-ids sg-12345678

# 출력 예시 (인바운드 규칙)
# IpPermissions:
#   - IpProtocol: tcp
#     FromPort: 80
#     ToPort: 80
#     IpRanges: [{CidrIp: 0.0.0.0/0}]   # 전체 허용
#   - IpProtocol: tcp
#     FromPort: 22
#     ToPort: 22
#     IpRanges: [{CidrIp: 10.0.0.0/8}]  # 내부망만 허용

# Security Group에 인바운드 규칙 추가 (443 HTTPS)
aws ec2 authorize-security-group-ingress \
  --group-id sg-12345678 \
  --protocol tcp \
  --port 443 \
  --cidr 0.0.0.0/0

# 규칙 제거
aws ec2 revoke-security-group-ingress \
  --group-id sg-12345678 \
  --protocol tcp \
  --port 8080 \
  --cidr 0.0.0.0/0

Security Group 설계 원칙:

원칙 1: 최소 권한 — 필요한 포트만 열기
원칙 2: 소스 제한 — 0.0.0.0/0 대신 특정 IP/Security Group
원칙 3: 레이어 분리
  - ALB Security Group: 80, 443 → 0.0.0.0/0
  - EC2 Security Group: 80, 443 → ALB Security Group에서만 허용
  - RDS Security Group: 3306 → EC2 Security Group에서만 허용

AWS RDS 운영

💡개념

RDS — 관리형 DB 운영 기초

온프레미스에서 MySQL을 직접 관리하던 팀이 AWS로 전환하면서 처음 받는 질문이 있습니다. "RDS 슬로우 쿼리 로그는 어디서 보나요?", "백업은 자동으로 되나요?", "패치는 언제 적용되나요?" RDS는 관리를 AWS에 넘기는 대신 접근 방식이 완전히 달라집니다. OS에 직접 접근할 수 없고, 콘솔과 파라미터 그룹으로 모든 것을 조작합니다. 이 방식에 익숙해지기까지 처음 한두 달이 가장 어렵습니다.

온프레미스에서 MySQL 서버를 직접 설치·관리하던 것과 달리, RDS는 AWS가 백업, 패치, 이중화를 관리합니다. 운영팀은 연결 설정, 파라미터 튜닝, 모니터링에 집중하면 됩니다.

로컬 터미널
# RDS 인스턴스 목록 확인
aws rds describe-db-instances \
  --query "DBInstances[].[DBInstanceIdentifier,DBInstanceStatus,Endpoint.Address,EngineVersion]" \
  --output table

# RDS 엔드포인트 확인 (접속 주소)
aws rds describe-db-instances \
  --db-instance-identifier my-mysql-db \
  --query "DBInstances[0].Endpoint.Address" \
  --output text

# RDS에 MySQL 클라이언트로 접속 (EC2에서)
mysql -h my-db.xxxxxxxxx.ap-northeast-2.rds.amazonaws.com \
  -u admin -p mydb

# 읽기 복제본 목록 확인
aws rds describe-db-instances \
  --query "DBInstances[?ReadReplicaSourceDBInstanceIdentifier!=null].[DBInstanceIdentifier,Endpoint.Address]" \
  --output table

RDS 운영 체크리스트:

일상 점검:
  - RDS 콘솔 → CloudWatch 메트릭: CPU, 연결 수, IOPS
  - 자동 백업 보존 기간 확인 (기본 7일, 최대 35일)
  - 미처리 파라미터 그룹 변경 확인 (pending-reboot)

파라미터 그룹 주요 항목:
  - max_connections: 최대 연결 수 (인스턴스 메모리에 비례)
  - slow_query_log: 1 (활성화 권장)
  - long_query_time: 1 (1초 이상 슬로우 쿼리 기록)
  - innodb_buffer_pool_size: 메모리의 70~75%

AWS S3 운영

💡개념

S3 — 객체 스토리지 기본 활용

온프레미스에서 NFS를 쓰던 팀이 S3를 NFS처럼 쓰려다가 낭패를 봤습니다. 디렉터리 목록을 읽고 파일을 수정하는 방식으로 접근하니 기대했던 성능도, 사용법도 달랐습니다. S3는 디렉터리가 없고 파일을 수정하는 것도 전체를 재업로드하는 방식입니다. 하지만 용량 제한 없이 URL 하나로 접근할 수 있고, 버전 관리와 수명주기 정책도 내장되어 있습니다. 이 특성을 이해하면 어떤 용도에 맞는지 보입니다.

S3는 파일 시스템이 아닙니다. URL로 접근하는 객체 스토리지입니다. 정적 파일 배포, 백업 보관, 로그 아카이빙에 가장 많이 씁니다.

로컬 터미널
# S3 버킷 목록 확인
aws s3 ls

# 버킷 내용 확인
aws s3 ls s3://my-bucket/
aws s3 ls s3://my-bucket/logs/ --human-readable

# 파일 업로드
aws s3 cp /opt/dist/index.html s3://my-bucket/
aws s3 cp /opt/dist/ s3://my-bucket/static/ --recursive

# 파일 다운로드
aws s3 cp s3://my-bucket/backup/mysql_20260530.sql.gz /tmp/

# 동기화 (로컬 → S3, 변경된 파일만)
aws s3 sync /opt/dist/ s3://my-bucket/static/ --delete

# 파일 삭제
aws s3 rm s3://my-bucket/old-file.txt
aws s3 rm s3://my-bucket/old-dir/ --recursive

# 버킷 정책 확인
aws s3api get-bucket-policy --bucket my-bucket

S3 백업 활용 예시:

DB 클라이언트
# mysqldump 결과를 직접 S3로 업로드 (로컬 저장 없이)
mysqldump --single-transaction --all-databases | \
  gzip | \
  aws s3 cp - s3://my-bucket/backup/mysql_$(date +%Y%m%d).sql.gz

# S3 수명 주기 정책 — 30일 후 Glacier로 이전 (콘솔에서 설정)
# 90일 후 삭제 규칙 추가로 비용 관리

AWS CloudWatch 모니터링

💡개념

CloudWatch — EC2/RDS 메트릭과 로그 수집

EC2 인스턴스 CPU 알람을 설정했는데 실제 장애 때 알람이 오지 않았습니다. CloudWatch Agent를 설치하지 않아 메모리와 디스크 사용률은 수집이 안 되고 있었던 것입니다. AWS 기본 제공 메트릭에는 CPU는 있지만 메모리와 디스크는 포함되지 않습니다. 무엇이 자동 수집되고 무엇이 추가 설정이 필요한지를 파악하지 않으면 모니터링을 믿다가 사각지대에서 장애가 납니다.

온프레미스에서 Prometheus + Grafana로 하던 모니터링을 AWS에서는 CloudWatch로 기본 처리합니다. EC2 CPU, 메모리, 디스크 사용률을 수집하고 알람을 설정합니다.

로컬 터미널
# EC2 CPU 사용률 조회 (최근 1시간, 5분 단위)
aws cloudwatch get-metric-statistics \
  --namespace AWS/EC2 \
  --metric-name CPUUtilization \
  --dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --period 300 \
  --statistics Average \
  --output table

# RDS CPU 사용률 조회
aws cloudwatch get-metric-statistics \
  --namespace AWS/RDS \
  --metric-name CPUUtilization \
  --dimensions Name=DBInstanceIdentifier,Value=my-mysql-db \
  --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
  --period 300 \
  --statistics Average

# CloudWatch 로그 그룹 목록
aws logs describe-log-groups \
  --query "logGroups[].logGroupName" \
  --output text

# 로그 스트림 최근 항목 확인
aws logs get-log-events \
  --log-group-name /aws/ec2/myapp \
  --log-stream-name i-1234567890abcdef0 \
  --limit 50

CloudWatch 알람 설정 (CPU 80% 이상):

로컬 터미널
aws cloudwatch put-metric-alarm \
  --alarm-name "EC2-CPU-High" \
  --alarm-description "EC2 CPU 80% 초과" \
  --namespace AWS/EC2 \
  --metric-name CPUUtilization \
  --dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
  --period 300 \
  --evaluation-periods 2 \
  --threshold 80 \
  --comparison-operator GreaterThanThreshold \
  --statistic Average \
  --alarm-actions arn:aws:sns:ap-northeast-2:123456789:my-alerts

실습 — EC2 상태 확인과 CloudWatch 메트릭 조회

1EC2 인스턴스 목록과 상태 확인

AWS CLI가 설정된 환경에서 실행합니다. aws configure로 Access Key, Secret Key, 리전(ap-northeast-2)이 설정되어 있어야 합니다. 출력에서 인스턴스 ID, 상태(running/stopped), 공인 IP를 확인합니다.

OUTPUT
-------------------------------------------------------
|              DescribeInstances                      |
+---------------------+----------+------------------+
| i-0abc123def456789  | running  | 13.124.xxx.xxx  |
| i-0def456abc123789  | stopped  | None            |
+---------------------+----------+------------------+
aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId,State.Name,PublicIpAddress]' --output table
🔍실행 후 확인할 것
  • describe-instances 결과에서 State.Name을 먼저 확인 — running/stopped/terminated가 구분되어야 함. 결과가 비어있으면 리전 설정 오류(aws configure에서 region 확인) 또는 IAM 권한 없음
  • PublicIpAddress가 없는 인스턴스는 퍼블릭 접근 불가 — Private Subnet에 있는 것. Name 태그가 없으면 인스턴스 구분이 어려워 운영 사고 위험이 있으므로 태깅 표준 적용 필요
  • 조회된 인스턴스 수가 예상보다 적으면 — aws configure에 설정된 리전과 실제 인스턴스 리전이 다른 것. aws ec2 describe-instances --region ap-northeast-2로 리전을 명시해서 재확인
2CloudWatch EC2 CPU 메트릭 조회

최근 1시간 동안의 CPU 사용률을 5분 단위로 조회합니다. --statistics Average 외에 Maximum, Minimum도 함께 확인하면 스파이크 여부를 알 수 있습니다. 인스턴스 ID는 1단계에서 확인한 것으로 교체합니다.

aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name CPUUtilization --dimensions Name=InstanceId,Value=i-0abc123def456789 --period 300 --statistics Average --start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ) --end-time $(date -u +%Y-%m-%dT%H:%M:%SZ)
🔍실행 후 확인할 것
  • CloudWatch 메트릭 결과에서 Average 값을 먼저 확인 — 80% 미만이면 정상. 80~90%면 주의, 90% 이상이면 인스턴스 타입 업그레이드 또는 Auto Scaling 검토 필요
  • Datapoints가 0개이면 메트릭 데이터 없음 — 인스턴스 ID가 잘못됐거나 시작 시각(--start-time)이 너무 오래된 것. EC2 기본 모니터링은 5분 간격이므로 --period를 300 미만으로 설정하면 데이터 없음
  • CPU 사용률 80% 이상이고 Security Group에 0.0.0.0/0으로 22번이 열린 조합이면 — 외부 공격으로 인한 자원 고갈 가능성. SSH brute force 로그(auth.log)와 함께 확인

클라우드 전환 고려사항

💡개념

온프레미스 → AWS 전환 시 실제로 고려해야 하는 것들

AWS로 전환한다고 운영이 자동으로 쉬워지지 않습니다. 온프레미스에서 쓰던 패턴이 그대로 통하지 않는 부분이 있고, 클라우드에서만 발생하는 새로운 이슈도 있습니다.

네트워크 지연:
  온프레미스: 서버 간 1ms 이하 레이턴시
  AWS 같은 리전 내: 수 ms (AZ 간 1~3ms)
  → 마이크로서비스 간 호출이 많다면 지연 영향 측정 필요

비용 최적화:
  - Reserved Instance(예약 인스턴스): 1~3년 약정으로 최대 72% 할인
  - Spot Instance: 유휴 용량 활용, 최대 90% 할인 (중단 가능)
  - Right-sizing: 과도하게 큰 인스턴스 타입 사용 여부 점검
  → Cost Explorer로 서비스별 비용 확인 필수

보안 설정:
  - 기본 VPC와 Security Group 설정이 너무 열려 있는 경우 흔함
  - IAM 역할 최소 권한 원칙 적용
  - S3 버킷 공개 접근 차단 확인 (Public Access Block)
  - CloudTrail 활성화 (API 호출 감사 로그)

하이브리드 운영 — 온프레미스와 AWS 연계:

로컬 터미널
# AWS VPN 연결 상태 확인 (Site-to-Site VPN)
aws ec2 describe-vpn-connections \
  --query "VpnConnections[].State" \
  --output text

# VPN 터널 상태 확인
aws ec2 describe-vpn-connections \
  --query "VpnConnections[].VgwTelemetry[].[OutsideIpAddress,Status,StatusMessage]" \
  --output table

AWS ALB 기초

💡개념

ALB — 타겟 그룹과 헬스체크

배포 후 일부 사용자만 오류를 경험한다고 신고했습니다. ALB 뒤에 있는 두 인스턴스 중 하나가 헬스체크에 실패해 unhealthy 상태가 됐는데, ALB는 여전히 두 인스턴스에 트래픽을 보내고 있었습니다. 헬스체크 경로가 실제 동작하지 않는 경로로 설정되어 있었던 것입니다. ALB 헬스체크는 장애 인스턴스를 자동 제외하는 핵심 기능이지만, 경로와 응답 코드를 올바르게 설정하지 않으면 제대로 동작하지 않습니다.

온프레미스에서 L4/L7 로드밸런서(F5, HAProxy)를 쓰던 역할을 AWS에서는 ALB(Application Load Balancer)가 합니다.

로컬 터미널
# ALB 목록 확인
aws elbv2 describe-load-balancers \
  --query "LoadBalancers[].[LoadBalancerName,State.Code,DNSName]" \
  --output table

# 타겟 그룹 헬스 상태 확인
aws elbv2 describe-target-health \
  --target-group-arn arn:aws:elasticloadbalancing:ap-northeast-2:123456789:targetgroup/my-tg/abcdef

# 출력 예시:
# HealthStatus: healthy / unhealthy / unused
# Reason: Target.ResponseCodeMismatch (헬스체크 응답 코드 불일치)

# 리스너 규칙 확인 (HTTPS → HTTP 리다이렉트 등)
aws elbv2 describe-listeners \
  --load-balancer-arn arn:aws:elasticloadbalancing:ap-northeast-2:123456789:loadbalancer/app/my-alb/abcdef

트러블슈팅

원인: EC2 인스턴스의 Security Group Outbound 규칙에서 외부 트래픽이 차단됐거나, NAT Gateway/인터넷 게이트웨이 설정 문제입니다.

로컬 또는 서버
# EC2에서 외부 연결 테스트
curl -v --connect-timeout 5 https://api.example.com
# connect: Connection timed out → 네트워크 레벨 차단

# Security Group Outbound 규칙 확인
aws ec2 describe-security-groups \
  --group-ids sg-12345678 \
  --query "SecurityGroups[].IpPermissionsEgress"
# All traffic 0.0.0.0/0 이 없으면 아웃바운드 차단

# 아웃바운드 전체 허용 추가
aws ec2 authorize-security-group-egress \
  --group-id sg-12345678 \
  --protocol -1 \
  --cidr 0.0.0.0/0

# Private 서브넷이면 NAT Gateway 확인
# 라우팅 테이블에 0.0.0.0/0 → NAT Gateway 경로 있는지 확인
aws ec2 describe-route-tables \
  --filters Name=association.subnet-id,Values=subnet-12345678

원인: EC2에서 RDS로의 연결이 Security Group 또는 서브넷 설정으로 차단됐습니다. RDS와 EC2가 같은 VPC에 있어도 Security Group 설정이 없으면 연결이 안 됩니다.

로컬 터미널
# RDS Security Group 확인
aws rds describe-db-instances \
  --db-instance-identifier my-mysql-db \
  --query "DBInstances[0].VpcSecurityGroups"

# RDS Security Group의 인바운드 규칙 확인
aws ec2 describe-security-groups \
  --group-ids sg-rds-98765432
# 3306 포트에 EC2 Security Group이 소스로 지정됐는지 확인

# EC2 Security Group을 소스로 RDS 인바운드 규칙 추가
aws ec2 authorize-security-group-ingress \
  --group-id sg-rds-98765432 \
  --protocol tcp \
  --port 3306 \
  --source-group sg-ec2-12345678

# nc로 포트 연결 테스트 (EC2에서 실행)
nc -zv my-db.xxxxxxxxx.ap-northeast-2.rds.amazonaws.com 3306
# Connection to my-db... 3306 port [tcp/mysql] succeeded! → 포트 열림

심화 — 클라우드에서 가장 비싼 실수는 네트워크가 아니라 권한이다

💡개념

심화: IAM 최소 권한 — 키가 아니라 역할, 그리고 폭발 반경(blast radius)

앞의 두 트러블은 '연결이 안 되는' 문제였습니다. 그런데 클라우드에서 가장 크게 터지는 사고는 대개 연결이 아니라 권한에서 옵니다 — 잘못 열린 권한 하나가 계정 전체를 위험에 빠뜨립니다.

  • 키가 아니라 역할(role): 장수(long-lived) 액세스 키를 코드·환경변수·설정에 심으면, 그 키는 git 커밋·로그·프런트엔드 번들 어디로든 유출됩니다. EC2·Lambda에는 IAM 역할(인스턴스 프로파일)을 붙여 STS가 발급하는 짧은 수명의 자동 교체 자격 증명을 쓰면, 심을 키 자체가 없어 유출 표면이 사라집니다.
  • 최소 권한이 폭발 반경을 줄인다: 정책을 필요한 액션·리소스로만 좁히면, 자격 증명이 탈취돼도 공격자가 할 수 있는 일이 제한됩니다. 반대로 역할에 AdministratorAccess* 권한을 붙여 두면 키 하나 유출이 곧 데이터 유출·리소스 삭제·크립토 마이닝 같은 계정 전체 장악으로 번집니다.
  • 통제 수단: 정책을 특정 액션·리소스·조건으로 스코프하고, 장수 키 대신 역할과 STS를 쓰며, 안 쓰는 키는 주기적으로 비활성화·회전합니다. CloudTrail(API 감사)·비용 알람·GuardDuty를 켜 이상 사용을 조기에 잡고, IAM Access Analyzer나 실제 CloudTrail 사용 이력으로 과도한 권한을 깎아 최소 권한에 맞춥니다.
  • 한계: '지금 동작한다'는 관대한 정책은 문제를 숨깁니다. 키가 새기 전까지는 아무 일도 없어 보이기 때문에, 위험은 유출되는 그 순간에야 청구서와 함께 드러납니다.

정리하면, 네트워크 오설정은 '연결이 안 되는' 불편이지만, 권한 오설정은 '무엇이든 되는' 재앙입니다. 그래서 최소 권한과 단수명 자격 증명이 클라우드 운영의 기본기입니다.

상황: 청구서가 갑자기 수십 배로 뛰어 확인해 보니, 평소 쓰지 않는 리전에 대형 GPU 인스턴스가 여러 대 실행 중입니다. 아무도 만든 기억이 없습니다.

원인: 넓은 권한을 가진 장수 IAM 액세스 키가 유출됐습니다. 공개 저장소에 커밋됐거나 프런트엔드 빌드·로그에 섞여 나간 키를, 공격자가 주워 여러 리전에 GPU 인스턴스를 띄워 크립토 마이닝에 쓴 것입니다. '장수 키 + 관대한 정책'의 조합이 폭발 반경을 계정 전체로 키웠습니다.

진단: CloudTrail에서 문제의 RunInstances 호출을 찾아 어느 IAM 주체(액세스 키 ID)가, 어느 소스 IP에서, 어느 리전들에 걸쳐 일으켰는지 추적합니다(공격자는 눈에 잘 안 띄는 us-east-1 등 안 쓰는 리전을 고릅니다). GuardDuty 탐지 결과도 함께 확인해 유출된 키와 피해 범위를 특정합니다.

해결: 즉시 해당 액세스 키를 비활성화·삭제하고 활성 세션을 무효화한 뒤, 전 리전의 불법 인스턴스를 종료하고 관련 시크릿을 모두 회전합니다. 그다음 근본 원인을 제거합니다 — 심어 둔 키를 인스턴스 역할·STS로 대체하고, 정책을 최소 권한으로 좁히며, 비용 알람과 GuardDuty를 켜고, 저장소를 비밀 스캔으로 점검합니다. 원칙은 하나입니다 — 장수 키는 언젠가 샌다고 가정하고, 최소 권한과 단수명 자격 증명으로 피해 범위를 미리 묶어 둡니다.

💼
실무 맥락
현업 패턴

실제 업무에서 클라우드 운영이 온프레미스와 다른 점:

클라우드로 전환하면 처음에는 뭔가 더 복잡하게 느껴질 수 있습니다. 하지만 인프라팀 관점에서 가장 크게 달라지는 것은 "물리 장비 교체 걱정이 없어진다"는 점입니다. 대신 비용 관리와 보안 설정이 새로운 일상 업무가 됩니다.

로컬 터미널
# 매일 아침 클라우드 운영 점검 루틴
# 1. EC2 인스턴스 상태
aws ec2 describe-instances --query "Reservations[].Instances[].[InstanceId,State.Name]" --output table

# 2. ALB 타겟 헬스
aws elbv2 describe-target-health --target-group-arn <arn>

# 3. RDS 상태
aws rds describe-db-instances --query "DBInstances[].[DBInstanceIdentifier,DBInstanceStatus]" --output table

# 4. 이번 달 비용 확인
aws ce get-cost-and-usage \
  --time-period Start=$(date +%Y-%m-01),End=$(date +%Y-%m-%d) \
  --granularity MONTHLY \
  --metrics BlendedCost

명령어·단축키 빠른 참조

이 모듈에서 다룬 AWS CLI 운영 명령(EC2·SG·RDS·S3·CloudWatch)을 실전 옵션과 함께 모았습니다.

명령어/단축키용도자주 쓰는 예
aws ec2 describe-instances인스턴스 목록·상태 조회--query "Reservations[].Instances[].[InstanceId,State.Name]" --output table
aws ssm start-sessionSSH 포트 없이 EC2 접속aws ssm start-session --target i-0abc…
aws ec2 start/stop/reboot-instances인스턴스 전원 제어aws ec2 stop-instances --instance-ids i-0abc…
aws ec2 authorize-security-group-ingressSG 인바운드 규칙 추가--group-id sg-… --protocol tcp --port 443 --cidr 0.0.0.0/0
aws ec2 describe-security-groupsSG 인·아웃바운드 규칙 확인--query "SecurityGroups[].IpPermissions"
aws rds describe-db-instancesRDS 상태·엔드포인트 조회--query "DBInstances[0].Endpoint.Address" --output text
aws s3 cp / syncS3 업·다운로드, 정적 배포aws s3 sync ./dist s3://bucket/static/ --delete
aws cloudwatch get-metric-statisticsEC2/RDS 메트릭 조회--namespace AWS/EC2 --metric-name CPUUtilization --period 300
aws cloudwatch put-metric-alarm임계치 경보 설정--threshold 80 --alarm-actions arn:aws:sns:…
aws logs get-log-eventsCloudWatch 로그 조회--log-group-name /aws/ec2/myapp --limit 50
aws elbv2 describe-target-healthALB 타겟 헬스 확인--target-group-arn arn:…:targetgroup/my-tg/…
aws ce get-cost-and-usage이번 달 비용 확인--granularity MONTHLY --metrics BlendedCost
nc -zvRDS 등 포트 연결 테스트nc -zv my-db….rds.amazonaws.com 3306
curl 169.254.169.254EC2 인스턴스 메타데이터 조회curl -s http://169.254.169.254/latest/meta-data/instance-id

온프레미스와 AWS를 함께 운영하는 하이브리드 환경에서는 VPN/Direct Connect 연결 상태가 서비스 연속성에 직결됩니다. 연결이 끊기면 양쪽 서버가 모두 떠 있어도 통신이 안 됩니다. 다음 모듈에서는 장애 대응, 인증서 만료, WAF 오탐, DB 커넥션 소진 등 실제 운영 시나리오를 종합해 다룹니다.

이 모듈이 다룬 AWS 운영 주제(IAM·VPC·EC2·RDS·비용)를 처음부터 체계적으로 깊게 배우고 싶다면 별도의 Cloud Engineering 트랙에서 계정·네트워크·컴퓨트·스토리지·서버리스·IaC·비용·보안·복원력까지 단계적으로 다룹니다. 출발점은 왜 클라우드인가이고, 마이그레이션 전략(마이그레이션 전략)과 설계 점검(Well-Architected)도 함께 보면 좋습니다.

지식 확인

퀴즈 — 8문제

Q1

AWS EC2 인스턴스의 보안 취약점 패치 작업 요청이 왔습니다. '클라우드니까 AWS가 알아서 관리하는 거 아닌가요?'라는 질문에 올바른 답변은?

Q2

AWS Security Group이 온프레미스 방화벽과 다른 점은?

Q3

AWS RDS를 직접 EC2에 MySQL 설치 대신 사용하는 주요 이유는?

Q4

AWS Systems Manager(SSM) Session Manager를 사용하는 이유는?

Q5

온프레미스의 NAS처럼 S3를 서버에 마운트해 파일시스템으로 쓰려다 막혔다. S3의 성격을 가장 잘 설명한 것은?

Q6

EC2의 CPU가 가끔 임계치를 넘는데 사람이 계속 보고 있을 수 없다. CloudWatch로 운영을 자동화하는 방법은?

Q7

[심화] EC2 위의 애플리케이션이 S3 버킷에 접근해야 한다. 보안상 가장 바람직한 자격 증명 방식은?

Q8

[심화] 이번 달 AWS 청구서가 평소의 수십 배로 뛰고, 켠 적 없는 리전에 GPU 인스턴스가 여러 대 떠 있다. 원인 규명을 위해 가장 먼저 볼 것은?

0 / 8 답변

🧪 실습으로 확인하기

Nginx 설치 및 기동

초급

Linux 서버에 Nginx를 설치하고 systemd 서비스로 등록하여 80포트에서 응답하는 상태까지 만든다.

40📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요