ArgoCD sync는 됐는데 Pod가 안 떠요 — 원인 추적기

도람·2026년 4월 30일

트러블슈팅

목록 보기
6/10

CrashLoopBackOff 해결기 — EKS Pod 살리기 (feat. ArgoCD 재설치)

저번 포스팅에서 ArgoCD 연결까지는 성공했는데, production Pod를 띄우는 과정에서 CrashLoopBackOff 오류가 발생했다.

이번 포스팅에서는 원인을 추적하고 해결하는 과정을 기록한다.

CrashLoopBackOff란?
컨테이너가 시작됐다가 바로 죽는 걸 반복하는 상태다.
쿠버네티스가 "계속 죽으니까 잠깐 기다렸다가 다시 시작할게" 하면서 점점 재시작 간격을 늘린다.
보통 앱 설정 오류, DB 연결 실패, 환경변수 누락 등이 원인이다.


1. EKS 연결

먼저 로컬에서 EKS 클러스터에 접근할 수 있도록 kubeconfig를 설정한다.

# kubeconfig 연결
aws eks update-kubeconfig --region ap-northeast-2 --name pposiraegi-cluster --profile goorm

# 노드 상태 확인
kubectl get nodes

노드가 Ready 상태로 뜨면 클러스터 연결은 정상이다.

노드(Node)란?
쿠버네티스에서 실제로 컨테이너가 실행되는 서버(가상머신)다.
EKS에서는 EC2 인스턴스가 노드 역할을 한다.


2. 어떤 Pod가 죽었는지 확인

kubectl get pods -n production

아무것도 뜨지 않았다.

-n production이란?
-n은 네임스페이스(namespace)를 지정하는 옵션이다.
쿠버네티스는 리소스를 네임스페이스라는 공간으로 분리해서 관리한다.
production은 실제 서비스가 올라가는 공간이다.

production 네임스페이스에 Pod가 하나도 없다는 건, ArgoCD가 아직 sync를 하지 않은 것이다.
즉, GitHub 레포에 있는 매니페스트 파일들이 클러스터에 아직 반영되지 않은 상태라는 뜻이다.

ArgoCD부터 다시 설치하고 연결해야 한다.


3. ArgoCD 재설치

# argocd 네임스페이스 생성
kubectl create namespace argocd

# 공식 매니페스트 적용
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

created 메시지들이 쭉 뜨면 설치가 진행 중인 것이다.

설치 완료 후 Pod 상태를 확인한다:

kubectl get pods -n argocd

모든 Pod의 STATUS가 Running으로 바뀌면 다음 단계로 넘어간다.
처음엔 ContainerCreating이나 Pending으로 뜨는 게 정상이니 잠깐 기다리면 된다.


4. ArgoCD UI 접속

ArgoCD는 웹 UI를 제공한다. 포트 포워딩으로 로컬에서 접속한다.

kubectl port-forward svc/argocd-server -n argocd 8080:443

포트 포워딩이란?
클러스터 내부 서비스를 외부에 노출하지 않고, 내 PC에서만 접근할 수 있도록 통로를 만드는 것이다.
위 명령어는 "내 PC의 8080번 포트로 들어오는 요청을 ArgoCD 서버의 443 포트로 전달해줘"라는 뜻이다.

브라우저에서 https://localhost:8080 접속 후 로그인한다.

초기 비밀번호 확인 (PowerShell):

kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | ForEach-Object { [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($_)) }
  • 아이디: admin
  • 비밀번호: 위 명령어 출력값

⚠️ 브라우저에서 "안전하지 않은 연결" 경고가 뜨면 고급 → 계속 진행을 누르면 된다.
자체 서명 인증서라서 뜨는 경고로, 로컬 개발 환경에서는 정상이다.


5. namespace 및 Secret 생성

ArgoCD가 배포할 production 네임스페이스와 DB/Redis 접속 정보를 미리 만들어줘야 한다.
이 작업을 먼저 해두지 않으면 Pod가 뜨다가 환경변수를 못 찾아서 바로 죽는다.

# namespace, configmap 먼저 생성
kubectl apply -f kubernetes/base/namespace.yaml
kubectl apply -f kubernetes/base/configmap.yaml

RDS, Redis 엔드포인트를 확인한다:

terraform output rds_endpoint
terraform output elasticache_endpoint

확인한 엔드포인트로 Secret을 생성한다:

kubectl create secret generic app-secret \
  --namespace=production \
  --from-literal=DB_HOST=RDS엔드포인트 \
  --from-literal=DB_USERNAME=pposiraegi \
  --from-literal=DB_PASSWORD=DB비밀번호 \
  --from-literal=REDIS_HOST=Redis엔드포인트 \
  --from-literal=JWT_SECRET=JWT시크릿

Secret이란?
비밀번호, API 키처럼 코드에 직접 넣으면 안 되는 민감한 값을 쿠버네티스 내부에서 안전하게 관리하는 리소스다.
--from-literal로 값을 넣으면 자동으로 base64로 인코딩되어 저장된다.
Pod에서는 환경변수 형태로 이 값을 꺼내 쓸 수 있다.


6. ArgoCD App 연결 및 Sync

kubectl apply -f argocd-app.yaml

터미널에서 직접 sync한다:

# argocd-server Pod 이름 먼저 확인
kubectl get pods -n argocd

# ArgoCD 서버에 로그인
kubectl -n argocd exec -it [argocd-server-Pod이름] -- \
  argocd login localhost:8080 --insecure --username admin --password [비밀번호]

# Sync 실행
kubectl -n argocd exec -it [argocd-server-Pod이름] -- \
  argocd app sync pposiraegi --insecure

exec -it란?
실행 중인 Pod 안으로 직접 들어가서 명령어를 실행하는 것이다.
마치 서버에 SSH로 접속해서 명령어를 치는 것과 같다.


7. Pod 상태 확인 및 로그 분석

kubectl get pods -n production

Pod들이 뜨기 시작하면 각 Pod의 로그를 확인한다:

# 현재 로그 확인
kubectl logs -n production [죽은Pod이름]

# 이미 죽은 컨테이너의 직전 로그 확인
kubectl logs -n production [죽은Pod이름] --previous

order-service Pod의 로그를 먼저 확인했다.

Connect timed out

원인 분석:

에러의미
Connect timed outRDS(데이터베이스)에 접속 요청을 보냈는데 응답이 없음
원인EKS 노드 → RDS 보안 그룹이 막혀있음

보안 그룹(Security Group)이란?
AWS에서 서버 간 트래픽을 허용/차단하는 방화벽 역할을 한다.
RDS의 보안 그룹에 EKS 노드가 포함되어 있지 않으면 아무리 올바른 주소로 접속해도 연결이 차단된다.


8. EKS 노드 보안 그룹을 동적으로 추가

EKS는 배포할 때마다 보안 그룹 ID가 바뀐다.
그래서 ID를 하드코딩하지 않고, Terraform이 자동으로 가져오도록 동적으로 연결했다.

왜 동적으로 해야 할까?
terraform apply를 할 때마다 EKS가 새 보안 그룹을 만든다.
매번 수동으로 ID를 복사해서 넣으면 실수가 생기고 유지보수가 어렵다.
Terraform 모듈끼리 연결해두면 항상 최신 ID를 자동으로 참조한다.

1) modules/security/variables.tf에 변수 추가

variable "eks_cluster_sg_id" {
  description = "EKS cluster security group ID"
  default     = ""
}

2) modules/security/main.tf 수정

RDS와 Redis 보안 그룹에 EKS 노드 접근 허용 규칙을 추가한다.

# RDS 보안 그룹 — PostgreSQL 5432 포트
ingress {
  from_port       = 5432
  to_port         = 5432
  protocol        = "tcp"
  security_groups = [var.eks_cluster_sg_id]
}

# Redis 보안 그룹 — Redis 6379 포트
ingress {
  from_port       = 6379
  to_port         = 6379
  protocol        = "tcp"
  security_groups = [var.eks_cluster_sg_id]
}

3) modules/eks/outputs.tf에 출력값 추가

EKS 모듈이 보안 그룹 ID를 외부로 내보낼 수 있도록 output을 추가한다.

output "cluster_security_group_id" {
  value = aws_eks_cluster.main.vpc_config[0].cluster_security_group_id
}

4) 루트 main.tf에서 모듈 간 연결

module "security" {
  source = "./modules/security"

  project_name      = var.project_name
  vpc_id            = module.networking.vpc_id
  eks_cluster_sg_id = module.eks.cluster_security_group_id  # EKS에서 자동으로 가져옴
}

이렇게 연결해두면 terraform apply를 할 때마다 EKS가 새로 만드는 보안 그룹 ID를 자동으로 참조한다.

수정 후 적용:

terraform apply -var-file="terraform.tfvars"

9. Terraform apply 후 ArgoCD 재sync

apply 후 ArgoCD 상태를 확인했는데 뭔가 이상해 보였다.

혹시 Secret이나 엔드포인트가 잘못됐나 싶어서 다시 확인했다.

Secret과 엔드포인트는 정상적으로 등록된 것을 확인했다. 그래서 다시 sync를 시도했다.

# ArgoCD 서버에 로그인
kubectl -n argocd exec -it argocd-server-78f5bb67d5-xt9g6 -- \
  argocd login localhost:8080 --insecure --username admin --password [패스워드]

# Sync 실행
kubectl -n argocd exec -it argocd-server-78f5bb67d5-xt9g6 -- \
  argocd app sync pposiraegi --insecure

각 명령어의 의미를 정리하면:

첫 번째 명령어 — ArgoCD 로그인

부분의미
kubectl -n argocd exec -it [Pod이름]argocd 네임스페이스의 argocd-server Pod 안으로 접속
argocd login localhost:8080Pod 안에서 ArgoCD에 로그인
--insecureHTTPS 인증서 검증 건너뛰기
--username admin --password [패스워드]admin 계정으로 로그인

두 번째 명령어 — App Sync

부분의미
kubectl -n argocd exec -it [Pod이름]argocd-server Pod 안으로 접속
argocd app sync pposiraegipposiraegi 앱을 GitHub 레포와 동기화
--insecureHTTPS 인증서 검증 건너뛰기


10. 그런데 또 문제가 — kubeconfig와 RBAC

여기까지 했는데도 production Pod가 여전히 뜨지 않았다.

팀원과 공유하는 과정에서 원인이 두 가지 더 있다는 걸 알게 됐다.

원인 1 — kubeconfig가 예전 엔드포인트를 가리키고 있음

terraform apply를 다시 하면 EKS 클러스터가 재생성되면서 API 서버 엔드포인트 주소가 바뀐다.
그런데 로컬의 kubeconfig는 예전 주소를 그대로 들고 있기 때문에, kubectl 명령어가 존재하지 않는 클러스터에 계속 요청을 보내고 있던 것이다.
해결 방법은 간단하다. aws eks update-kubeconfig를 다시 실행해서 최신 엔드포인트로 갱신해주면 된다.

aws eks update-kubeconfig --region ap-northeast-2 --name pposiraegi-cluster --profile goorm

원인 2 — RBAC 권한 문제

RBAC(Role-Based Access Control)란?
쿠버네티스에서 "누가 무엇을 할 수 있는지" 권한을 관리하는 시스템이다.
ArgoCD가 production 네임스페이스에 Pod를 배포하려면 그에 맞는 권한이 부여되어 있어야 한다.
권한이 없으면 sync는 성공해도 실제 리소스가 생성되지 않거나 오류가 발생한다.

이 두 가지 문제가 복합적으로 작용해서 production Pod가 계속 뜨지 않았던 것이다.


마무리

이번 포스팅에서 겪은 문제들을 정리하면:

순서문제원인해결
1CrashLoopBackOffEKS → RDS 보안 그룹 차단Terraform으로 동적 보안 그룹 연결
2kubectl 연결 안 됨kubeconfig가 예전 엔드포인트를 가리킴update-kubeconfig 재실행
3Pod 배포 안 됨ArgoCD RBAC 권한 누락다음 포스팅에서 해결 예정

트러블슈팅을 하다 보면 문제 하나를 해결하면 또 다른 문제가 나오는 게 일상이다.
RBAC 권한 설정과 부트스트랩 스크립트 적용 과정은 다음 포스팅에서 이어서 정리할 예정이다. 😅

profile
정도를 걷는 엔지니어

0개의 댓글