AWS Cloud School 13기 117일차

Forever 김·2026년 6월 23일

AWS Cloud School

목록 보기
109/116

2026-06-23

Today

항목상태
Jenkins SG → EKS cluster SG 443 inbound 추가
jenkins-tf-runner-dev EKS access entry + policy 등록
RDS가 plan마다 교체로 잡히는 문제 수정 — SSM placeholder 값 drift 방지 lifecycle 추가
Secrets Manager secret_version이 plan마다 교체로 잡히는 문제 수정 — provider v5.100 write-only 속성 drift 방지 lifecycle 추가
environments/dev/.checkov.yaml 생성 (checkov Failed 0)
feat 브랜치 Jenkins 파이프라인 SUCCESS (PR #71)
ArgoCD 7.7.0 → 9.6.0 (PR #72)
Jenkinsfile Helm cache 경로 수정 HELM_CACHE_HOME=/tmp/helm-cache (PR #73)
ArgoCD 9.6.0 prod apply✅ (UNSTABLE — checkov 2건)
prod/.checkov.yaml CKV_AWS_260·CKV_AWS_118 추가 시도 (PR #74) → 빌드 취소 + revert (PR #75)
feat/main 동기화 2회
Jenkins 초기 설정 완료 — Unlock(initialAdminPassword) → Suggested Plugins → admin 계정 생성 → Jenkins URL 확인
Docker Pipeline 플러그인 추가 설치 + EC2에 Docker 설치 (dnf install docker + usermod -aG docker jenkins)
GitHub Server 연동 — Secret text credential(github-pat-token) 등록 → Jenkins→GitHub commit status 보고 활성화
Branch Protection Rule 설정 — continuous-integration/jenkins/branch + pr-head 필수 check 등록
dev SSM 파라미터 5개 생성 (/farmily/dev/{container_image,db_name,db_username,db_password,s3_bucket_name})
AmazonSSMManagedInstanceCore 정책을 farmily-jenkins-ec2-role에 Terraform으로 연결 (SSM Session Manager 접속용)
GitOps farmily-app 이미지 태그 업데이트 prod-d7b6cd9prod-881c370 (PR #76)
KEDA syncOptionsServerSideApply=true 추가 (PR #77)
Jenkins ALB SG GitHub IPs only 교체0.0.0.0/0 → GitHub webhook IP 4 CIDR + IPv6 2개. namename_prefix 교체 (create_before_destroyInvalidGroup.Duplicate 방지)
Internal ALB 생성 후 삭제 — VPN + kubectl port-forward로 충분, 현재 불필요 판단
Jenkinsfile TF_SKIP 추가 — gitops 전용 커밋 시 Terraform 단계 전체 skip
PR #82 생성 + main 머지

Notes

Jenkins ALB SG 교체 삽질 기록

오늘 ALB SG를 0.0.0.0/0에서 GitHub webhook IP만 허용으로 바꾸면서 두 번 막혔다.

1차 — DependencyViolation (14분 대기)
create_before_destroy 없이 SG를 교체하면 Terraform이 구 SG 삭제를 먼저 시도한다. 그런데 ALB가 구 SG를 참조 중이라 AWS가 삭제를 거부한다. apply가 14분 넘게 멈춰 있어서 TaskStop으로 강제 중단하고 lifecycle { create_before_destroy = true }를 추가했다.

2차 — InvalidGroup.Duplicate
create_before_destroy를 추가하면 Terraform이 이번엔 신 SG를 먼저 만들고 구 SG를 나중에 지운다. 그런데 name = "farmily-jenkins-alb-sg"로 고정해 두면 신·구 SG가 같은 VPC에 잠깐 동시에 존재하는 순간이 생겨 AWS가 중복 이름 에러를 낸다. name_prefix = "farmily-jenkins-alb-sg-"로 바꿔서 매 교체마다 suffix가 달라지게 하니 해결됐다.

교훈: SG에 create_before_destroy를 쓸 거면 name이 아닌 name_prefix가 필수다. SG는 교체가 잦은 리소스라 처음 만들 때부터 name_prefix로 만드는 게 낫다.

Internal ALB는 왜 만들었다 지웠나

처음에 EKS pod 내부 접근을 위해 Internal ALB가 필요하다는 말을 듣고 바로 생성했다. 그런데 실제로 필요한 경우를 따져보니:

  • Jenkins: VPN 연결 후 10.0.10.250:8080으로 직접 접근 가능
  • Grafana, ArgoCD: kubectl port-forward로 접근 가능

팀 전원이 kubectl 없이 브라우저 접근이 필요한 시점이 오면 그때 Internal ALB를 추가하면 된다. 지금은 불필요해서 삭제했다.

Learned

  • create_before_destroy + name 충돌 — Terraform이 SG를 교체할 때 신 SG를 먼저 만들고 구 SG를 나중에 지우는데, name이 고정값이면 신·구가 같은 이름으로 VPC에 동시 존재하는 순간이 생겨 InvalidGroup.Duplicate 에러가 난다. name_prefix를 쓰면 매 교체마다 suffix가 달라져서 이름 충돌이 없다. SG description도 변경 불가(AWS immutable)라 설명을 바꾸면 교체(replace)가 강제된다.
  • DependencyViolation — AWS 리소스 간 참조 관계가 있을 때 삭제 순서가 잘못되면 발생하는 에러. ALB→SG 참조 상태에서 SG 삭제를 먼저 시도하면 "다른 리소스가 쓰고 있어서 삭제 불가"로 막힌다. create_before_destroy로 생성→교체→삭제 순서를 바꾸면 해결된다.
  • TargetGroupBinding (AWS LB Controller) — Kubernetes Ingress를 쓰지 않고 Terraform으로 ALB+TG를 생성한 뒤, TargetGroupBinding CRD로 K8s Service와 TG를 연결하는 패턴. LB Controller가 Pod IP 변화를 감지해서 TG에 자동 등록·해제한다. Ingress 없이도 ALB를 쓸 수 있는 구조다.
  • Split-horizon DNS — 같은 도메인 이름을 VPN 안에서는 내부 ALB로, 인터넷에서는 외부 ALB로 보내는 패턴. Route53 public hosted zone(외부)과 private hosted zone(VPN 클라이언트 전용)을 함께 쓰면 구현된다. VPN 연결 시 VPC DNS(10.0.0.2)가 push되고, private zone이 public zone보다 우선순위가 높아 내부 레코드를 먼저 반환한다.
  • Key Usage (X.509) — 인증서가 어떤 용도로만 사용 가능한지 제한하는 확장 필드. digitalSignature(TLS 핸드셰이크), keyEncipherment(키 교환), keyCertSign(CA 전용) 등이 있음. OpenVPN의 remote-cert-tls server는 서버 인증서에 Key Usage extension이 있어야 검증 통과함. 없으면 VERIFY KU ERROR로 핸드셰이크 실패. 인증서 발급 시 -extfile로 명시해야 함.
  • VPN ENI — Client VPN 엔드포인트를 서브넷에 associate하면 AWS가 자동 생성하는 네트워크 인터페이스(ENI). VPN 트래픽이 VPC 안으로 들어오는 진입점 역할. 라우트 타입이 Nat이면 VPN 클라이언트 IP(10.2.0.x)가 ENI IP(10.0.10.x)로 NAT 변환돼서, Jenkins 같은 대상 EC2 입장에서 소스 IP가 클라이언트가 아니라 ENI IP로 보임. 그래서 SG를 VPN CIDR이 아닌 ENI가 속한 서브넷 CIDR로 열어야 함.
  • DSL (Domain-Specific Language) — 특정 분야 전용으로 만든 언어. 범용 언어(Python, Java)와 달리 한 가지 목적에 최적화된 문법만 제공. 예: HCL(인프라), Jenkinsfile(CI/CD), SQL(데이터), Dockerfile(컨테이너). Jenkins의 docker { } 같은 구문은 Docker Pipeline 플러그인이 제공하는 DSL이라, 플러그인 없으면 No such DSL method 에러 발생.

Prompt(회고)

오늘은 Jenkins ALB 하나 고치면서 에러를 두 번 만났다. 처음엔 create_before_destroy가 없어서 DependencyViolation이 났고, 추가하고 나니 이번엔 이름 중복 에러가 났다. 에러 자체는 별거 아니었는데 왜 이렇게 되는지 이해하는 데 시간이 걸렸다. AWS가 SG를 교체하는 동안 신·구가 동시에 존재한다는 게 생각보다 직관적이지 않았다. 그냥 넘기면 또 같은 실수를 할 것 같아서 Notes에 전 과정을 남겨뒀다.

Internal ALB는 만들었다 지웠다. 필요하다는 말을 듣고 바로 만들었는데, 실제로 어떤 상황에서 필요한지를 먼저 확인했어야 했다. VPN으로 직접 IP 접근이 되고 port-forward도 되는 상황에서 ALB까지 굳이 만들 이유가 없었다. 오늘 배운 것: 뭔가 만들기 전에 "지금 이게 없으면 뭐가 안 되는가"를 먼저 따지자.

내일은 또 멘토링이 잡혀있다. 다시 한번 AWS 현직자 분에게 언제 멘토링을 받을 수 있을지 모르기 때문에 열심히해야함을 상기하자

profile
나를 한줄로

0개의 댓글