LogoSkills

aws-infrastructure-rules

AWS infrastructure operations rules โ€” SSM/RDS access from private VPC. Use when accessing RDS/SSM from a private VPC, setting up bastion/port-forwarding, or troubleshooting AWS infra access.

AWS Infrastructure Operations Rules#

ํ•œ๋งˆ๋””๋กœ (๋น„๊ฐœ๋ฐœ์ž์šฉ)#

์ด ๋ฌธ์„œ๋Š” ์„œ๋น„์Šค๊ฐ€ ๋Œ์•„๊ฐ€๋Š” "ํด๋ผ์šฐ๋“œ ์„œ๋ฒ„์‹ค(AWS)"์—์„œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ ์“ฐ๋Š” ์‘๊ธ‰์กฐ์น˜ ๋งค๋‰ด์–ผ์ž…๋‹ˆ๋‹ค. ๋งˆ์น˜ ๊ฑด๋ฌผ ๊ด€๋ฆฌ์‹ค์— ๋ถ™์€ "์ •์ „ ์‹œ ๋‘๊บผ๋น„์ง‘ ํ™•์ธํ•˜์„ธ์š”", "์ˆ˜๋„ ์ž ๊ฒผ์„ ๋•Œ ๋ฐธ๋ธŒ ์—ฌ๋Š” ๋ฒ•" ๊ฐ™์€ ์•ˆ๋‚ด๋ฌธ๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ๋ฉˆ์ถ”๊ฑฐ๋‚˜ ๋А๋ ค์กŒ์„ ๋•Œ, ์–ด๋””๋ถ€ํ„ฐ ์ ๊ฒ€ํ•˜๊ณ  ์–ด๋–ป๊ฒŒ ๋˜์‚ด๋ฆฌ๋Š”์ง€๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ์ •๋ฆฌํ•ด ๋‘” ๋น„์ƒ ๋Œ€์‘์ง‘์ด๋ผ๊ณ  ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋ฌด์—‡์„ยท์–ธ์ œ (๋น„๊ฐœ๋ฐœ์ž์šฉ)#

  • ๋ฌด์—‡์„ ํ•ด์ฃผ๋‚˜์š”
    • ์„œ๋ฒ„๊ฐ€ 502/503 ๊ฐ™์€ ์—๋Ÿฌ๋กœ "์ ๊ฒ€ ์ค‘" ํ™”๋ฉด์„ ๋„์šธ ๋•Œ ์›์ธ์„ ์ฐพ์•„ ๋ณต๊ตฌํ•˜๋Š” ์ ˆ์ฐจ๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
    • ๋ฐ์ดํ„ฐ ์ €์žฅ ๊ณต๊ฐ„(DB ๋””์Šคํฌ)์ด ๊ฝ‰ ์ฐผ์„ ๋•Œ ๊ธด๊ธ‰์œผ๋กœ ๊ณต๊ฐ„์„ ๋Š˜๋ฆฌ๋Š” ๋ฐฉ๋ฒ•์„ ์•ˆ๋‚ดํ•ฉ๋‹ˆ๋‹ค.
    • ๋น„๋ฐ€๋ฒˆํ˜ธ(ํ† ํฐ) ๋ถˆ์ผ์น˜๋กœ ์บ์‹œ ๊ธฐ๋Šฅ์ด ๋ฉˆ์ท„์„ ๋•Œ ๋‹ค์‹œ ๋งž์ถ”๋Š” ๋ฐฉ๋ฒ•์„ ์•ˆ๋‚ดํ•ฉ๋‹ˆ๋‹ค.
    • ๋ฐฐํฌ(์ƒˆ ๋ฒ„์ „ ์ ์šฉ)๊ฐ€ ์‹คํŒจํ•˜๊ฑฐ๋‚˜, ๊ฐœ๋ฐœ์ž PC์˜ ๊ฐ€์ƒํ™˜๊ฒฝ์ด ์ž ๊ฒผ์„ ๋•Œ ํ‘ธ๋Š” ๋ฐฉ๋ฒ•์„ ์•ˆ๋‚ดํ•ฉ๋‹ˆ๋‹ค.
    • ์žฅ์• ๊ฐ€ ๋‚ฌ์„ ๋•Œ "๋ฌด์—‡๋ถ€ํ„ฐ ํ™•์ธํ• ์ง€" ์ ๊ฒ€ ์ˆœ์„œ๋ฅผ ์ œ์‹œํ•ฉ๋‹ˆ๋‹ค (๋ณดํ†ต DB ์ €์žฅ๊ณต๊ฐ„์„ ๊ฐ€์žฅ ๋จผ์ € ๋ด…๋‹ˆ๋‹ค).
  • ์–ธ์ œ ์ž‘๋™ํ•˜๋‚˜์š”
    • ์šด์˜/์Šคํ…Œ์ด์ง• ์„œ๋ฒ„์— ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ.
    • ๋น„๊ณต๊ฐœ๋ง(์™ธ๋ถ€์—์„œ ์ง์ ‘ ์ ‘์† ๋ถˆ๊ฐ€) ์•ˆ์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ ๊ฒ€ํ•ด์•ผ ํ•  ๋•Œ.
    • ๋ฐฐํฌ ํ›„ ์ƒˆ ๋ฒ„์ „์ด ์‹ค์ œ๋กœ ์ž˜ ๋–ด๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์„ ๋•Œ.

ํ•ต์‹ฌ ์šฉ์–ด (๋น„๊ฐœ๋ฐœ์ž์šฉ)#

์šฉ์–ด์‰ฌ์šด ์„ค๋ช…
AWS์„œ๋น„์Šค๊ฐ€ ์‹ค์ œ๋กœ ๋Œ์•„๊ฐ€๋Š” ์•„๋งˆ์กด์˜ ํด๋ผ์šฐ๋“œ ์„œ๋ฒ„์‹ค
RDS๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๊ด€ํ•˜๋Š” ํด๋ผ์šฐ๋“œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค (์ €์žฅ ์ฐฝ๊ณ )
storage-full๋ฐ์ดํ„ฐ ์ฐฝ๊ณ (๋””์Šคํฌ)๊ฐ€ ๊ฝ‰ ์ฐจ์„œ ๋” ๋ชป ์“ฐ๋Š” ์ƒํƒœ
EC2 / ASG์„œ๋ฒ„ ์ปดํ“จํ„ฐ ํ•œ ๋Œ€(EC2)์™€, ํŠธ๋ž˜ํ”ฝ์— ๋งž์ถฐ ์ž๋™์œผ๋กœ ๋Œ€์ˆ˜๋ฅผ ๋Š˜๋ฆฌ๊ณ  ์ค„์ด๋Š” ๋ฌถ์Œ(ASG)
VPC (private)์™ธ๋ถ€์—์„œ ์ง์ ‘ ๋ชป ๋“ค์–ด์˜ค๊ฒŒ ๋ง‰์•„ ๋‘” ๋‚ด๋ถ€ ์ „์šฉ ๋„คํŠธ์›Œํฌ
SSM๊ทธ ๋‚ด๋ถ€๋ง ์„œ๋ฒ„์— ์•ˆ์ „ํ•˜๊ฒŒ ์›๊ฒฉ ๋ช…๋ น์„ ๋ณด๋‚ด๋Š” ํ†ต๋กœ
ElastiCache / Redis์ž์ฃผ ์“ฐ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ๊บผ๋‚ด ์“ฐ๋Š” ์ž„์‹œ ์ €์žฅ์†Œ(์บ์‹œ)
AUTH token์บ์‹œ ์ ‘์†์šฉ ๋น„๋ฐ€๋ฒˆํ˜ธ
WRONGPASS๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์•ˆ ๋งž์•„ ์บ์‹œ ์ ‘์†์ด ๊ฑฐ๋ถ€๋œ ์—๋Ÿฌ
drift์„ค๊ณ„ ๋ฌธ์„œ(์ฝ”๋“œ)์™€ ์‹ค์ œ ์„œ๋ฒ„ ์ƒํƒœ๊ฐ€ ์–ด๊ธ‹๋‚œ ์ƒํ™ฉ
Terraform์„œ๋ฒ„ ๊ตฌ์„ฑ์„ ์ฝ”๋“œ๋กœ ์ ์–ด ๋‘๊ณ  ๊ทธ๋Œ€๋กœ ๋งŒ๋“ค์–ด ์ฃผ๋Š” ๋„๊ตฌ (์„ค๊ณ„๋„)
CodeDeploy์ƒˆ๋กœ ๋งŒ๋“  ๋ฒ„์ „์„ ์„œ๋ฒ„์— ์ž๋™์œผ๋กœ ๋ฐฐํฌํ•ด ์ฃผ๋Š” ๋„๊ตฌ
Blue/Green ๋ฐฐํฌ์ƒˆ ๋ฒ„์ „์„ ์˜†์— ๋”ฐ๋กœ ๋„์›Œ ๋‘๊ณ  ํ•œ ๋ฒˆ์— ๊ฐˆ์•„๋ผ์šฐ๋Š” ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ๋ฐฉ์‹
CloudWatch ์•Œ๋žŒ์„œ๋ฒ„ ์ƒํƒœ(CPU, ๋‚จ์€ ๊ณต๊ฐ„ ๋“ฑ)๋ฅผ ๊ฐ์‹œํ•˜๋‹ค ์œ„ํ—˜ํ•˜๋ฉด ์•Œ๋ ค ์ฃผ๋Š” ๊ฒฝ๋ณด
Colima VM๊ฐœ๋ฐœ์ž PC์—์„œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋Œ๋ฆฌ๊ธฐ ์œ„ํ•œ ๋กœ์ปฌ ๊ฐ€์ƒ ๋จธ์‹ 

AWS ์ธํ”„๋ผ ์žฅ์•  ๋Œ€์‘ ๋ฐ ์šด์˜ ๊ทœ์น™์ž…๋‹ˆ๋‹ค.


SSM์œผ๋กœ VPC ๋‚ด๋ถ€ RDS ์ฟผ๋ฆฌ ์‹คํ–‰#

ํ”„๋กœ๋•์…˜/์Šคํ…Œ์ด์ง• RDS๋Š” private VPC์— ์œ„์น˜ํ•ด ๋กœ์ปฌ์—์„œ ์ง์ ‘ ์ ‘์† ๋ถˆ๊ฐ€. SSM Send-command + EC2์—์„œ ์ผํšŒ์„ฑ postgres ์ปจํ…Œ์ด๋„ˆ๋กœ psql ์‹คํ–‰ํ•œ๋‹ค.

์ ˆ์ฐจ#

# 1. EC2 ์ธ์Šคํ„ด์Šค ID ์กฐํšŒ (ASG ๊ต์ฒด ๋Œ€๋น„ โ€” ๋งค๋ฒˆ ๋‹ค์‹œ ์กฐํšŒ ํ•„์ˆ˜)
INSTANCE_ID=$(aws ec2 describe-instances \
  --filters  " Name=tag:Environment,Values=production "   \
             " Name=instance-state-name,Values=running "   \
  --query  ' Reservations[0].Instances[0].InstanceId '   --output text)

# 2. DB ์—ฐ๊ฒฐ ์ •๋ณด ํ™•์ธ (์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€)
aws ssm send-command --instance-ids $INSTANCE_ID \
  --document-name  " AWS-RunShellScript "   \
  --parameters  ' commands=[ " docker exec kobic-server cat config/production.yaml | grep -A6 \ " ^database:\ " " ] ' 

 # 3. postgres ์ด๋ฏธ์ง€ pre-pull (์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ์— ์‹œ๊ฐ„ ๊ฑธ๋ฆฌ๋ฉด send-command ํƒ€์ž„์•„์›ƒ)
aws ssm send-command --instance-ids $INSTANCE_ID \
  --document-name  " AWS-RunShellScript "   \
  --parameters  ' commands=[ " docker pull postgres:15-alpine " ] ' 

 # 4. psql ์ฟผ๋ฆฌ ์‹คํ–‰
aws ssm send-command --instance-ids $INSTANCE_ID \
  --document-name  " AWS-RunShellScript "   \
  --parameters  ' commands=[ " docker run --rm --network host -e PGPASSWORD= < password >   postgres:15-alpine psql -h  < db-host >   -U postgres -d serverpod -c \ " < SQL > \ " " ] '

๊ฒฐ๊ณผ polling ํŒจํ„ด#

CMD_ID=$(...)  # send-command ๋ฐ˜ํ™˜๊ฐ’

until aws ssm get-command-invocation \
  --command-id $CMD_ID --instance-id $INSTANCE_ID \
  --query  ' Status '   --output text | grep -qE  " ^(Success|Failed)$ " ; do
  sleep 3
done

aws ssm get-command-invocation --command-id $CMD_ID \
  --instance-id $INSTANCE_ID \
  --query  ' [Status,StandardOutputContent] '   --output text

์ฃผ์˜#

  • psql์€ kobic-server ์ปจํ…Œ์ด๋„ˆ์— ํฌํ•จ๋˜์ง€ ์•Š์Œ โ†’ ๋ฐ˜๋“œ์‹œ ๋ณ„๋„ postgres:15-alpine ์ปจํ…Œ์ด๋„ˆ ์‚ฌ์šฉ
  • ASG ๊ต์ฒด๋กœ EC2 ์ธ์Šคํ„ด์Šค ID๋Š” ์ž์ฃผ ๋ฐ”๋€œ โ†’ ํ•˜๋“œ์ฝ”๋”ฉ ๊ธˆ์ง€, ๋งค๋ฒˆ ์กฐํšŒ
  • DB ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” kobic-server ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€ config/passwords.yaml์—์„œ runmode ์„น์…˜๋ณ„๋กœ ๋ถ„๋ฆฌ๋จ

์ฐธ๊ณ : 2026-04-18 ํ”„๋กœ๋•์…˜ drift ์ง„๋‹จยท์ˆ˜๋™ migration ๋™๊ธฐํ™” ์‹œ ํ™œ์šฉ (Issue #5022)


ElastiCache AUTH์™€ SSM Parameter Store ๋™๊ธฐํ™” ์ด์Šˆ#

์ฆ์ƒ#

RedisError(WRONGPASS invalid username-password pair or user is disabled)

์„œ๋ฒ„ ๋กœ๊ทธ์— ๋ฐ˜๋ณต์ ์œผ๋กœ ์ถœ๋ ฅ. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ Redis ์˜์กด ๊ธฐ๋Šฅ(์บ์‹œ ๋“ฑ) ๋™์ž‘ ์‹คํŒจ.

์›์ธ#

Terraform์ด ๊ด€๋ฆฌํ•˜๋Š” 3๊ฐœ ๋ฆฌ์†Œ์Šค ๊ฐ„ ๋™๊ธฐํ™”๊ฐ€ ๊นจ์งˆ ์ˆ˜ ์žˆ์Œ:

๋ฆฌ์†Œ์Šค์—ญํ• 
random_password.redis_auth_tokenํ† ํฐ ์ƒ์„ฑ
aws_ssm_parameter.redis_auth_tokenSSM Parameter Store ์ €์žฅ (์„œ๋ฒ„๊ฐ€ ์ฐธ์กฐ)
aws_elasticache_replication_group.xxx.auth_token์‹ค์ œ Redis ํด๋Ÿฌ์Šคํ„ฐ AUTH

Terraform apply ๋ถ€๋ถ„ ์‹คํŒจ ๋˜๋Š” ์ˆ˜๋™ ๋ณ€๊ฒฝ์œผ๋กœ SSM๊ณผ ElastiCache ๊ฐ’์ด ์–ด๊ธ‹๋‚˜๋ฉด WRONGPASS.

์ง„๋‹จ#

# SSM ํŒŒ๋ผ๋ฏธํ„ฐ ์ตœ์ข… ๋ณ€๊ฒฝ์ผ
aws ssm describe-parameters \
  --parameter-filters  " Key=Name,Values=/kobic/staging/redis/auth-token "   \
  --query  ' Parameters[0].[LastModifiedDate,Version] '   --output text

# ElastiCache AUTH ์ตœ์ข… ๋ณ€๊ฒฝ์ผ
aws elasticache describe-replication-groups \
  --replication-group-id kobic-staging \
  --query  ' ReplicationGroups[0].AuthTokenLastModifiedDate '   --output text

๋‘ ๋‚ ์งœ๊ฐ€ ํฌ๊ฒŒ ์ฐจ์ด๋‚˜๋ฉด drift ํ™•์ •.

ํ•ด๊ฒฐ โ€” ROTATE ์ „๋žต#

SSM ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ElastiCache๋ฅผ ๋™๊ธฐํ™”:

# 1. SSM์—์„œ AUTH ํ† ํฐ ์กฐํšŒ
TOKEN=$(aws ssm get-parameter \
  --name /kobic/staging/redis/auth-token --with-decryption \
  --query  ' Parameter.Value '   --output text)

# 2. ElastiCache AUTH ROTATE
aws elasticache modify-replication-group \
  --replication-group-id kobic-staging \
  --auth-token  " $TOKEN "   \
  --auth-token-update-strategy ROTATE \
  --apply-immediately

# 3. ์™„๋ฃŒ ํ™•์ธ (PendingAuthTokenStatus: None, Status: available)
aws elasticache describe-replication-groups \
  --replication-group-id kobic-staging \
  --query  ' ReplicationGroups[0].{Status:Status,PendingAuthTokenStatus:PendingModifiedValues.AuthTokenStatus} ' 

 # 4. ์ปจํ…Œ์ด๋„ˆ ์žฌ์‹œ์ž‘ โ€” ํ•„์ˆ˜ (๊ธฐ์กด connection ์บ์‹œ๊ฐ€ old token ์œ ์ง€)
aws ssm send-command --instance-ids  < INSTANCE_ID >   \
  --parameters  ' commands=[ " docker restart kobic-server " ] '

์ „๋žต ์„ ํƒ#

์ „๋žตํšจ๊ณผ์‚ฌ์šฉ ์‹œ์ 
ROTATE๊ธฐ์กด + ์‹ ๊ทœ ํ† ํฐ ๋‘˜ ๋‹ค ํ—ˆ์šฉ์ผ๋ฐ˜์  drift ๋ณต๊ตฌ (๊ถŒ์žฅ)
SET์‹ ๊ทœ ํ† ํฐ๋งŒ ํ—ˆ์šฉ๊ธ‰ํ•œ ๋ณด์•ˆ ์กฐ์น˜
DELETEAUTH ๋น„ํ™œ์„ฑํ™”๋“œ๋ฌพ

ROTATE ํ•œ ๋ฒˆ ํ›„์—๋„ ๊ธฐ์กด ํ† ํฐ์ด ์—ฌ์ „ํžˆ ํ—ˆ์šฉ ์ƒํƒœ์ด๋ฏ€๋กœ, ์™„์ „ ์ „ํ™˜ ์‹œ ํ•œ ๋ฒˆ ๋” ROTATE ํ•„์š”.

์ฐธ๊ณ : Issue #5023์—์„œ Staging ElastiCache AUTH(2026-02-12)์™€ SSM(2026-04-02) ๊ฐ„ 2๊ฐœ์›” drift ๋ณต๊ตฌ.


RDS Storage-Full ์žฅ์•  ๋Œ€์‘#

์ฆ์ƒ#

  • ์„œ๋ฒ„ 502/503 ์—๋Ÿฌ (์•ฑ์—์„œ "์„œ๋ฒ„ ์ ๊ฒ€ ์ค‘" ํ™”๋ฉด)
  • RDS ์ธ์Šคํ„ด์Šค ์ƒํƒœ: storage-full
  • CloudWatch FreeStorageSpace ๋ฉ”ํŠธ๋ฆญ์ด 0์— ๋„๋‹ฌ

์ง„๋‹จ ์ˆœ์„œ#

์ธํ”„๋ผ ์žฅ์•  ๋ฐœ์ƒ ์‹œ RDS๋ฅผ ๊ฐ€์žฅ ๋จผ์ € ํ™•์ธํ•ฉ๋‹ˆ๋‹ค (๊ฐ€์žฅ ํ”ํ•œ ์›์ธ).

# 1. RDS ์ธ์Šคํ„ด์Šค ์ƒํƒœ ํ™•์ธ
aws rds describe-db-instances \
  --db-instance-identifier kobic-staging \
  --query  ' DBInstances[0].{Status:DBInstanceStatus,Storage:AllocatedStorage,MaxStorage:MaxAllocatedStorage,FreeStorage:FreeStorageSpace} ' 

 # 2. FreeStorageSpace ๋ฉ”ํŠธ๋ฆญ ํ™•์ธ (์ตœ๊ทผ 1์‹œ๊ฐ„)
aws cloudwatch get-metric-statistics \
  --namespace AWS/RDS \
  --metric-name FreeStorageSpace \
  --dimensions Name=DBInstanceIdentifier,Value=kobic-staging \
  --start-time $(date -u -v-1H +%Y-%m-%dT%H:%M:%S) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
  --period 300 --statistics Minimum \
  --output table

# 3. ์Šคํ† ๋ฆฌ์ง€ ์‚ฌ์šฉ ์›์ธ ๋ถ„์„ (DB ์ ‘์† ํ›„)
SELECT pg_size_pretty(pg_database_size( ' serverpod ' )) as db_size;

-- ํ…Œ์ด๋ธ”๋ณ„ ์šฉ๋Ÿ‰ ํ™•์ธ
SELECT schemaname, tablename,
       pg_size_pretty(pg_total_relation_size(schemaname|| ' . ' ||tablename)) as total_size
FROM pg_tables
WHERE schemaname =  ' public ' 
 ORDER BY pg_total_relation_size(schemaname|| ' . ' ||tablename) DESC
LIMIT 20;

-- WAL ์‚ฌ์ด์ฆˆ ํ™•์ธ
SELECT pg_size_pretty(pg_wal_size()) as wal_size;

์Šคํ† ๋ฆฌ์ง€ ํ™•์žฅ ์ ˆ์ฐจ#

# ๊ธด๊ธ‰ ์Šคํ† ๋ฆฌ์ง€ ํ™•์žฅ (์ฆ‰์‹œ ์ ์šฉ, ๋‹ค์šดํƒ€์ž„ ์—†์Œ)
aws rds modify-db-instance \
  --db-instance-identifier kobic-staging \
  --allocated-storage 200 \
  --max-allocated-storage 500 \
  --apply-immediately

# ํ™•์žฅ ์ง„ํ–‰ ์ƒํƒœ ํ™•์ธ (storage-optimization ์ƒํƒœ๊ฐ€ ๋จ)
aws rds describe-db-instances \
  --db-instance-identifier kobic-staging \
  --query  ' DBInstances[0].DBInstanceStatus '

์ฃผ์˜์‚ฌํ•ญ:

  • RDS ์Šคํ† ๋ฆฌ์ง€ ํ™•์žฅ์€ ์ถ•์†Œ ๋ถˆ๊ฐ€ (ํ•œ๋ฒˆ ๋Š˜๋ฆฌ๋ฉด ์ค„์ผ ์ˆ˜ ์—†์Œ)
  • ํ™•์žฅ ํ›„ 6์‹œ๊ฐ„ ์ฟจ๋‹ค์šด (์ถ”๊ฐ€ ํ™•์žฅ ๋ถˆ๊ฐ€)
  • storage-optimization ์ƒํƒœ์—์„œ๋„ DB๋Š” ์ •์ƒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

Replication Slot ์ •๋ฆฌ#

CDC(Change Data Capture)์šฉ replication slot์ด ์Šคํ† ๋ฆฌ์ง€๋ฅผ ์†Œ๋น„ํ•˜๋Š” ์ฃผ์š” ์›์ธ์ž…๋‹ˆ๋‹ค.

-- replication slot ์ƒํƒœ ํ™•์ธ
SELECT slot_name, slot_type, active,
       pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) as retained_wal
FROM pg_replication_slots;

-- ๋น„ํ™œ์„ฑ slot ์‚ญ์ œ (ClickHouse ClickPipe ์—ฐ๊ฒฐ ๋Š๊ธด ๊ฒฝ์šฐ)
SELECT pg_drop_replication_slot( ' slot_name_here ' );

Terraform ์ฝ”๋“œ Drift ์ด์Šˆ#

๊ธด๊ธ‰ ํ™•์žฅ ํ›„ Terraform ์ฝ”๋“œ์™€ ์‹ค์ œ ์ธํ”„๋ผ๊ฐ€ ๋ถˆ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค. ๋ณ„๋„ ์ด์Šˆ๋กœ ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ™˜๊ฒฝTerraform ์ฝ”๋“œ (ํ˜„์žฌ)์‹ค์ œ ์ธํ”„๋ผ (ํ™•์žฅ ํ›„)ํ•„์š”ํ•œ ๋ณ€๊ฒฝ
staging allocated_storage=20, max=50 allocated_storage=200, max=500 ์ฝ”๋“œ ์—…๋ฐ์ดํŠธ ํ•„์š”
production allocated_storage=20, max=100 ํ™•์ธ ํ•„์š” ์ƒํ™ฉ์— ๋”ฐ๋ผ

ํŒŒ์ผ ์œ„์น˜: backend/kobic_server/deploy/aws/terraform/variables.tf (line 203-235, db_configs ๋ณ€์ˆ˜)


CodeDeploy ASG ๋ˆ„์  ๋ฌธ์ œ#

์ฆ์ƒ#

  • ๋ฐฐํฌ ์‹œ CodeDeploy๊ฐ€ ์˜ค๋ž˜๋œ (์ด๋ฏธ ์‚ญ์ œ๋œ) ASG์— ๋ฐฐํฌ ์‹œ๋„
  • ๋ฐฐํฌ ์‹คํŒจ ๋˜๋Š” ์ง€์—ฐ

์›์ธ#

CodeDeploy Deployment Group์— ๊ณผ๊ฑฐ Auto Scaling Group ์ด๋ฆ„์ด ๋‚จ์•„ ์žˆ์Œ. ASG๋ฅผ ์žฌ์ƒ์„ฑ(terraform destroy/apply)ํ•  ๋•Œ CodeDeploy๊ฐ€ ์ž๋™ ์ •๋ฆฌํ•˜์ง€ ์•Š์Œ.

์ง„๋‹จ#

# CodeDeploy Deployment Group์˜ ASG ๋ชฉ๋ก ํ™•์ธ
aws deploy get-deployment-group \
  --application-name kobic-app \
  --deployment-group-name kobic-staging-dg \
  --query  ' deploymentGroupInfo.autoScalingGroups[].name ' 

 # ์‹ค์ œ ์กด์žฌํ•˜๋Š” ASG ํ™•์ธ
aws autoscaling describe-auto-scaling-groups \
  --query  ' AutoScalingGroups[?contains(AutoScalingGroupName, `kobic`)].AutoScalingGroupName '

ํ•ด๊ฒฐ#

# ์˜ฌ๋ฐ”๋ฅธ ASG๋งŒ ํฌํ•จํ•˜๋„๋ก Deployment Group ์—…๋ฐ์ดํŠธ
aws deploy update-deployment-group \
  --application-name kobic-app \
  --current-deployment-group-name kobic-staging-dg \
  --auto-scaling-groups  " kobic-staging-asg "    # ํ˜„์žฌ ์œ ํšจํ•œ ASG๋งŒ ์ง€์ •

์˜ˆ๋ฐฉ#

  • Terraform์—์„œ ASG ์žฌ์ƒ์„ฑ ์‹œ CodeDeploy Deployment Group๋„ ํ•จ๊ป˜ ์—…๋ฐ์ดํŠธ๋˜๋Š”์ง€ ํ™•์ธ
  • CI/CD ํŒŒ์ดํ”„๋ผ์ธ์— stale ASG ์ •๋ฆฌ ์Šคํฌ๋ฆฝํŠธ ์ถ”๊ฐ€ ๊ฒ€ํ† 

Colima VM ๋””์Šคํฌ ์ž ๊น€ (๋กœ์ปฌ ๊ฐœ๋ฐœ)#

์ฆ์ƒ#

  • colima start ์‹คํŒจ
  • ์—๋Ÿฌ ๋ฉ”์‹œ์ง€: disk is locked ๋˜๋Š” qemu: could not acquire disk lock

์›์ธ#

Colima VM์ด ๋น„์ •์ƒ ์ข…๋ฃŒ๋˜์–ด ๋””์Šคํฌ ํŒŒ์ผ์— ๋ฝ์ด ๋‚จ์•„ ์žˆ์Œ.

ํ•ด๊ฒฐ#

# 1. Colima ๊ฐ•์ œ ์ข…๋ฃŒ
colima stop --force

# 2. ๋ฝ ํŒŒ์ผ ์ œ๊ฑฐ
rm -f ~/.colima/default/diffdisk  # ๋˜๋Š” ํ•ด๋‹น ํ”„๋กœํŒŒ์ผ ๊ฒฝ๋กœ
rm -f ~/.lima/colima/diffdisk

# 3. QEMU ํ”„๋กœ์„ธ์Šค ์ •๋ฆฌ
pkill -f qemu-system

# 4. ์žฌ์‹œ์ž‘
colima start

๋Œ€์•ˆ: ๋ฌธ์ œ๊ฐ€ ์ง€์†๋˜๋ฉด VM ์‚ญ์ œ ํ›„ ์žฌ์ƒ์„ฑ

colima delete
colima start --cpu 4 --memory 8 --disk 60

Docker ๊ธฐ๋ฐ˜ ๋ฐฐํฌ ์›Œํฌํ”Œ๋กœ์šฐ#

๋ฐฐํฌ ํ๋ฆ„#

GitHub Actions โ†’ Docker Build โ†’ ECR Push โ†’ CodeDeploy โ†’ ASG Instance
๋‹จ๊ณ„๋„๊ตฌ์„ค๋ช…
๋นŒ๋“œGitHub ActionsDocker ์ด๋ฏธ์ง€ ๋นŒ๋“œ
์ €์žฅAmazon ECR์ด๋ฏธ์ง€ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ
๋ฐฐํฌCodeDeployRolling ๋ฐฐํฌ
์‹คํ–‰EC2 (ASG)Docker Compose๋กœ ์‹คํ–‰

๋ฐฐํฌ ๋Œ€์ƒ๋ณ„ ๋ธŒ๋žœ์น˜#

ํ™˜๊ฒฝ์ฝ”๋“œ ๋ฐ˜์˜ ๋ธŒ๋žœ์น˜๋ฐฐํฌ ๋ฐฉ๋ฒ•
Staging development GitHub Actions workflow_dispatch
Production main main ๋ธŒ๋žœ์น˜ push ์‹œ ์ž๋™ ๋ฐฐํฌ

CodeDeploy ๋ฐฐํฌ ๊ทธ๋ฃน ๋ช…๋ช…#

ํ™˜๊ฒฝApplicationDeployment Group๋ฐฐํฌ ์ „๋žต
Staging kobic-app kobic-staging-group in-place (kobic-staging-group-base ASG ์žฌ์‚ฌ์šฉ)
Production kobic-app kobic-production-group Blue/Green (์‹ ๊ทœ ASG ์ƒ์„ฑ, ๊ตฌ ASG ์ด๋ฆ„: CodeDeploy_kobic-production-group_d-XXX)

์ฃผ์˜: ๊ณผ๊ฑฐ ๋ฌธ์„œ์— kobic-staging-dg๊ฐ€ ์–ธ๊ธ‰๋˜์—ˆ๋”๋ผ๋„ ์‹ค์ œ ์ด๋ฆ„์€ kobic-staging-group ์ž…๋‹ˆ๋‹ค. aws deploy list-deployment-groups --application-name kobic-app๋กœ ํ˜„์žฌ ์ƒํƒœ ํ™•์ธ.

์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€ ํƒœ๊ทธ ํ˜•์‹#

{env}-{shortSha}-{timestamp}
์˜ˆ: production-8023d1ba-20260418005915
    staging-87eec5a2-20260418084056

shortSha๋Š” ๋จธ์ง€ commit์˜ ์•ž 8์ž๋ฆฌ. ํƒœ๊ทธ๋กœ ๋ฐฐํฌ๋œ ๋ฒ„์ „์„ ์—ญ์ถ”์ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐฐํฌ ๋ฐ˜์˜ ๊ฒ€์ฆ ๋ฃจํ‹ด#

ํ”„๋กœ๋•์…˜ ๋ฐฐํฌ ํ›„ ์‹ค์ œ ์ปจํ…Œ์ด๋„ˆ์— ์ƒˆ ์ด๋ฏธ์ง€๊ฐ€ ์‹คํ–‰ ์ค‘์ธ์ง€ ํ™•์ธ:

# 1. ์ตœ์‹  CodeDeploy ๋ฐฐํฌ ID ์กฐํšŒ
aws deploy list-deployments \
  --application-name kobic-app \
  --deployment-group-name kobic-production-group \
  --max-items 1 \
  --query  ' deployments[0] '   --output text

# 2. ๋ฐฐํฌ ์ƒํƒœ ํ™•์ธ (Succeeded ์ธ์ง€)
aws deploy get-deployment --deployment-id  < id >   \
  --query  ' deploymentInfo.{Status:status,CompleteTime:completeTime} ' 

 # 3. ํ˜„์žฌ ์„œ๋น„์Šค ์ค‘์ธ EC2 ์ธ์Šคํ„ด์Šค ์กฐํšŒ (Blue/Green์ด๋ฉด ์ƒˆ ASG)
aws autoscaling describe-auto-scaling-groups \
  --query  ' AutoScalingGroups[?contains(AutoScalingGroupName, `production`)].{Name:AutoScalingGroupName,ID:Instances[0].InstanceId} ' 

 # 4. ์‹คํ–‰ ์ค‘ ์ปจํ…Œ์ด๋„ˆ ์ด๋ฏธ์ง€ ํ™•์ธ (SSM send-command)
aws ssm send-command --instance-ids  < id >   \
  --document-name  " AWS-RunShellScript "   \
  --parameters  ' commands=[ " docker ps --format \ " { { .Image } }   { { .Status } } \ "   | grep kobic " ] '   \
  --query  ' Command.CommandId '   --output text

# 5. ๊ฒฐ๊ณผ ํ™•์ธ (๋ช…๋ น ์‹คํ–‰ ํ›„ ~6์ดˆ ๋Œ€๊ธฐ)
aws ssm get-command-invocation \
  --command-id  < command-id >   --instance-id  < id >   \
  --query  ' StandardOutputContent '   --output text

์„œ๋ฒ„ ๋กœ๊ทธ ์ถ”์ถœ (IAP ๋“ฑ ๊ธฐ๋Šฅ๋ณ„ ๋””๋ฒ„๊น…):

# ์ตœ๊ทผ 30๋ถ„ IAP ๊ด€๋ จ ๋กœ๊ทธ
aws ssm send-command --instance-ids  < id >   \
  --document-name  " AWS-RunShellScript "   \
  --parameters  ' commands=[ " docker logs $(docker ps --format \ " { { .ID } } \ "   | head -1) --since 30m 2 > & 1 | grep -E \ " \\[IAP\\]|App Store\ "   | tail -40 " ] '

CloudWatch ์•Œ๋žŒ ์„ค์ • ํ˜„ํ™ฉ#

ํ˜„์žฌ ์„ค์ •๋œ ์•Œ๋žŒ#

์•Œ๋žŒ์ž„๊ณ„๊ฐ’alarm_actions
database-high-cpu80%๋นˆ ๋ฐฐ์—ด (์•Œ๋ฆผ ์—†์Œ)
database-high-connections50๊ฐœ์„ค์ • ์—†์Œ

๋ฏธ์„ค์ • (๊ถŒ์žฅ ์ถ”๊ฐ€)#

์•Œ๋žŒ๊ถŒ์žฅ ์ž„๊ณ„๊ฐ’์šฉ๋„
FreeStorageSpace< 5GBRDS ์Šคํ† ๋ฆฌ์ง€ ๋ถ€์กฑ ์‚ฌ์ „ ๊ฐ์ง€
FreeableMemory< 256MBRDS ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ๊ฐ์ง€
SwapUsage> 256MB๋ฉ”๋ชจ๋ฆฌ ์Šค์™‘ ๋ฐœ์ƒ ๊ฐ์ง€

์ฐธ๊ณ : ํ˜„์žฌ alarm_actions = []๋กœ ์„ค์ •๋˜์–ด ์žˆ์–ด ์•Œ๋žŒ์ด ๋ฐœ์ƒํ•ด๋„ ์•Œ๋ฆผ์ด ์ „๋‹ฌ๋˜์ง€ ์•Š์Œ. SNS ํ† ํ”ฝ ์—ฐ๊ฒฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.


์ธํ”„๋ผ ๋””๋ฒ„๊น… ์ˆœ์„œ (์žฅ์•  ๋ฐœ์ƒ ์‹œ)#

์žฅ์•  ๋ฐœ์ƒ ์‹œ ์•„๋ž˜ ์ˆœ์„œ๋กœ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค:

1. RDS ์ƒํƒœ ํ™•์ธ (storage-full์ด ๊ฐ€์žฅ ํ”ํ•œ ์›์ธ)
   โ†“
2. EC2/ASG ์ธ์Šคํ„ด์Šค ์ƒํƒœ ํ™•์ธ
   โ†“
3. Target Group ํ—ฌ์Šค์ฒดํฌ ํ™•์ธ
   โ†“
4. ALB ์ ‘๊ทผ ๋กœ๊ทธ ํ™•์ธ
   โ†“
5. CodeDeploy ๋ฐฐํฌ ์ƒํƒœ ํ™•์ธ
   โ†“
6. CloudWatch ๋กœ๊ทธ ํ™•์ธ

๋น ๋ฅธ ์ƒํƒœ ํ™•์ธ ๋ช…๋ น์–ด#

# RDS ์ƒํƒœ
aws rds describe-db-instances \
  --query  ' DBInstances[*].{ID:DBInstanceIdentifier,Status:DBInstanceStatus,Storage:AllocatedStorage} '   \
  --output table

# ASG ์ธ์Šคํ„ด์Šค ์ƒํƒœ
aws autoscaling describe-auto-scaling-groups \
  --query  ' AutoScalingGroups[?contains(AutoScalingGroupName,`kobic`)].{Name:AutoScalingGroupName,Desired:DesiredCapacity,Instances:Instances[*].{ID:InstanceId,Health:HealthStatus } } '   \
  --output json

# Target Group ํ—ฌ์Šค
aws elbv2 describe-target-health \
  --target-group-arn  < target-group-arn >   \
  --output table

# ์ตœ๊ทผ ๋ฐฐํฌ ์ƒํƒœ
aws deploy list-deployments \
  --application-name kobic-app \
  --deployment-group-name kobic-staging-dg \
  --max-items 3 \
  --query  ' deployments '

ํ›„์† ์ž‘์—… (TODO)#

์•„๋ž˜ ํ•ญ๋ชฉ๋“ค์€ ์ธํ”„๋ผ ์•ˆ์ •์„ฑ ํ–ฅ์ƒ์„ ์œ„ํ•ด ๋ณ„๋„ ์ด์Šˆ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

HIGH (๊ธด๊ธ‰)#

  • RDS FreeStorageSpace CloudWatch ์•Œ๋žŒ ์ถ”๊ฐ€: Terraform database.tf์— FreeStorageSpace < 5GB ์•Œ๋žŒ ์ถ”๊ฐ€
  • alarm_actions์— SNS ํ† ํ”ฝ ์—ฐ๊ฒฐ: ํ˜„์žฌ ๋นˆ ๋ฐฐ์—ด๋กœ ์„ค์ •๋œ ๊ธฐ์กด ์•Œ๋žŒ์— deployment_sns_topic_arn ์—ฐ๊ฒฐ
  • Terraform variables.tf staging db_configs ์—…๋ฐ์ดํŠธ: allocated_storage: 20โ†’200, max_allocated_storage: 50โ†’500
  • Replication slot ์Šคํ† ๋ฆฌ์ง€ ์›์ธ ๋ถ„์„: ClickHouse ClickPipe CDC slot์˜ WAL retention ํ™•์ธ ๋ฐ ์ตœ์ ํ™”
  • Redis AUTH ์„ค์ • ํ™•์ธ: Redis ์ ‘์† ์‹œ ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ด€๋ จ ์ด์Šˆ ์ ๊ฒ€

MEDIUM#

  • stale ASG ์ •๋ฆฌ ์ž๋™ํ™”: CodeDeploy Deployment Group์—์„œ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ASG ์ž๋™ ์ œ๊ฑฐ
  • replication slot ๋ชจ๋‹ˆํ„ฐ๋ง ์ถ”๊ฐ€: retained WAL ํฌ๊ธฐ ๊ธฐ๋ฐ˜ ์•Œ๋žŒ ์„ค์ •
  • ์ •๊ธฐ ์ •๋ฆฌ ํฌ๋ก ์žก: ์˜ค๋ž˜๋œ ๋ฐฐํฌ ์•„ํ‹ฐํŒฉํŠธ, ๋กœ๊ทธ ๋“ฑ ์ž๋™ ์ •๋ฆฌ
  • deletion_protection ํ™˜๊ฒฝ๋ณ„ ๋ถ„๋ฆฌ: production๋งŒ true, staging/development๋Š” false ์œ ์ง€ (ํ˜„์žฌ ๋ชจ๋‘ false)

LOW (์ž๋™ํ™” ์Šคํ‚ฌ ํ›„๋ณด)#

ํ–ฅํ›„ Claude Code ์Šคํ‚ฌ๋กœ ์ž๋™ํ™” ๊ฐ€๋Šฅํ•œ ํŒจํ„ด๋“ค:

์Šคํ‚ฌ๋ช…์šฐ์„ ์ˆœ์œ„์„ค๋ช…
aws/ssm-execHIGHSSM์œผ๋กœ EC2 ์ธ์Šคํ„ด์Šค์— ๋ช…๋ น ์‹คํ–‰
aws/rds-monitorHIGHRDS ์ƒํƒœ/๋ฉ”ํŠธ๋ฆญ ์‹ค์‹œ๊ฐ„ ํ™•์ธ
aws/healthHIGH์ „์ฒด ์ธํ”„๋ผ ํ—ฌ์Šค์ฒดํฌ ๋Œ€์‹œ๋ณด๋“œ
aws/tg-healthMEDIUMTarget Group ํ—ฌ์Šค์ฒดํฌ ์ƒํƒœ ํ™•์ธ
aws/asg-cleanupMEDIUMstale ASG/๋ฐฐํฌ ๊ทธ๋ฃน ์ •๋ฆฌ
aws/incident-responseLOW์žฅ์•  ๋Œ€์‘ ์ž๋™ํ™” ๋Ÿฐ๋ถ

๊ด€๋ จ ํŒŒ์ผ#

  • backend/kobic_server/deploy/aws/terraform/variables.tf - RDS/ASG ์„ค์ • (root)
  • backend/kobic_server/deploy/aws/terraform/modules/environment/database.tf - RDS ์ธ์Šคํ„ด์Šค ๋ฐ CloudWatch ์•Œ๋žŒ
  • backend/kobic_server/deploy/aws/terraform/modules/environment/variables.tf - ํ™˜๊ฒฝ๋ณ„ ๋ณ€์ˆ˜ ์ •์˜
  • backend/kobic_server/deploy/aws/terraform/modules/environment/compute.tf - ASG/EC2 ์„ค์ •
  • backend/kobic_server/deploy/aws/terraform/modules/shared/codedeploy.tf - CodeDeploy ์•ฑ ์„ค์ •
  • backend/kobic_server/deploy/aws/terraform/modules/environment/codedeploy.tf - ํ™˜๊ฒฝ๋ณ„ Deployment Group