개요
이번 글에서는 Kustomize의 secretGenerator를 사용해 Secret을 생성하던 중, Argo CD에서 동기화 오류가 발생한 문제를 정리합니다.
로컬에서는 .env 파일을 기준으로 Secret을 생성해 사용할 수 있었지만, 해당 .env 파일은 민감 정보이기 때문에 GitHub에 업로드하지 않았습니다. 그 결과 Argo CD가 Git 저장소를 기준으로 매니페스트를 생성하는 과정에서 .env 파일을 찾지 못해 에러가 발생했습니다.
문제 상황
Kustomize에서 다음과 같은 방식으로 Secret을 생성하고 있었습니다.
secretGenerator:
- name: user-database-secret
envs:
- secrets/user-database-secret.env
그리고 Deployment에서는 해당 Secret을 참조해 환경 변수를 주입받는 구조였습니다.
로컬 환경에서는 secrets/user-database-secret.env 파일이 존재했기 때문에 정상적으로 동작했습니다. 하지만 이 파일은 데이터베이스 비밀번호 같은 민감 정보를 포함하고 있어 GitHub에는 업로드하지 않았습니다.
이후 Argo CD에서 Application을 동기화하려고 하자 다음과 같은 에러가 발생했습니다.
ComparisonError
Failed to load target state: failed to generate manifest for source 1 of 1: rpc error: code = Unknown desc = `kustomize build <path to cached source>/k8s/services/overlays/local` failed exit status 1: Error: loading KV pairs: env source files: [secrets/user-database-secret.env]: evalsymlink failure on '<path to cached source>/k8s/services/overlays/local/secrets/user-database-secret.env' : lstat <path to cached source>/k8s/services/overlays/local/secrets/user-database-secret.env: no such file or directory
원인 분석
에러의 핵심은 다음 부분입니다.
secrets/user-database-secret.env: no such file or directory
Argo CD는 Git 저장소에 있는 파일을 기준으로 매니페스트를 생성합니다. 즉, Argo CD가 kustomization.yaml을 읽고 kustomize build를 실행할 때, secretGenerator에 명시된 .env 파일도 함께 존재해야 합니다.
하지만 실제 구조는 다음과 같았습니다.
- Kustomize의
secretGenerator는.env파일을 읽어 Kubernetes Secret을 생성한다. - Deployment는 생성된 Secret을 참조해 환경 변수를 사용한다.
- 민감 정보가 포함된
.env파일은 GitHub에 업로드하지 않았다. - Argo CD는 Git 저장소를 기준으로
kustomize build를 실행한다. - Git 저장소에는
.env파일이 없으므로 Secret 생성에 실패한다. - 결과적으로 Argo CD의 비교 및 동기화 과정에서
ComparisonError가 발생한다.
정리하면, Kustomize가 필요로 하는 입력 파일은 Argo CD가 접근 가능한 Git 저장소 안에 있어야 하는데, Secret의 기반이 되는 .env 파일이 Git에 없어서 발생한 문제였습니다.
해결 방법
해결 방법은 크게 몇 가지가 있습니다.
1. Sealed Secrets 사용
Sealed Secrets를 사용하면 Secret 값을 암호화된 형태로 Git에 저장할 수 있습니다.
Git에는 일반 Secret이 아니라 암호화된 SealedSecret 리소스를 저장하고, 클러스터 내부의 컨트롤러가 이를 복호화해 실제 Kubernetes Secret을 생성합니다.
이 방식은 GitOps 흐름과 잘 맞지만, 별도의 Sealed Secrets 컨트롤러 설치와 키 관리가 필요합니다.
2. External Secrets Operator 사용
운영 환경에서는 External Secrets Operator, 즉 ESO를 사용하는 방법도 있습니다.
ESO는 AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager 같은 외부 Secret 저장소에서 값을 가져와 Kubernetes Secret으로 동기화할 수 있습니다.
이 방식은 민감 정보를 Git에 직접 저장하지 않으면서도 Argo CD 기반 배포 흐름을 유지할 수 있다는 장점이 있습니다.
운영 환경이라면 단순히 Secret을 수동 생성하는 방식보다는 ESO 같은 Secret 관리 도구를 도입하는 것이 더 적절해 보입니다.
3. Secret을 클러스터에 직접 생성
이번에는 로컬 테스트 환경이었기 때문에 가장 단순한 방식으로 해결했습니다.
kustomization.yaml에서 secretGenerator 설정을 제거하고, Secret을 미리 생성하는 스크립트를 별도로 작성했습니다.
흐름은 다음과 같습니다.
- Secret 생성 스크립트를 실행한다.
- Kubernetes 클러스터에 Secret을 먼저 생성한다.
- Argo CD에서 Application을 Sync한다.
- Deployment는 이미 생성된 Secret을 참조한다.
즉, Argo CD가 Kustomize를 실행할 때 더 이상 Git에 없는 .env 파일을 참조하지 않도록 변경했습니다.
예를 들어 다음과 같은 방식으로 Secret을 미리 생성할 수 있습니다.
kubectl create secret generic user-database-secret \
--from-env-file=secrets/user-database-secret.env \
-n <namespace>
이미 동일한 이름의 Secret이 존재할 수 있다면 다음처럼 dry-run과 apply를 조합해 사용할 수도 있습니다.
kubectl create secret generic user-database-secret \
--from-env-file=secrets/user-database-secret.env \
-n <namespace> \
--dry-run=client -o yaml | kubectl apply -f -
위 명령어에서
<namespace>는 실제 Secret을 사용할 네임스페이스로 변경해야 합니다.
적용 결과
kustomization.yaml에서 secretGenerator를 제거한 뒤, Secret을 먼저 생성하고 Argo CD Sync를 다시 실행했습니다.
그 결과 Argo CD가 더 이상 Git에 없는 .env 파일을 찾지 않았고, Application이 정상적으로 배포되는 것을 확인했습니다.
이번 방식은 로컬 테스트 환경에서는 간단하게 적용할 수 있는 해결책이었습니다. 다만 운영 환경에서는 Secret을 수동으로 생성하는 방식이 관리 포인트를 늘릴 수 있습니다.
따라서 운영 환경에서는 다음과 같은 방식을 고려하는 것이 좋습니다.
- Sealed Secrets를 사용해 암호화된 Secret을 Git에 저장
- External Secrets Operator를 사용해 외부 Secret 저장소와 연동
- Secret 생성 및 갱신 방식을 배포 프로세스 안에서 명확하게 관리
정리
이번 문제는 Kustomize의 secretGenerator 자체 문제라기보다는, Argo CD가 Git 저장소를 기준으로 매니페스트를 생성한다는 점을 고려하지 않아 발생한 문제였습니다.
로컬에는 .env 파일이 존재했지만, GitHub에는 해당 파일이 없었고 Argo CD는 GitHub에 있는 파일만 기준으로 kustomize build를 실행했습니다. 따라서 secretGenerator가 참조하는 .env 파일을 찾지 못해 배포가 실패했습니다.
로컬 테스트 환경에서는 Secret을 미리 생성하는 방식으로 해결할 수 있었습니다.
하지만 운영 환경에서는 Secret을 GitOps 흐름 안에서 안전하게 관리할 수 있도록 Sealed Secrets나 External Secrets Operator 같은 도구를 사용하는 것이 더 적절합니다.
'Devops > Kubernetes' 카테고리의 다른 글
| Helm으로 Argo CD 설치 후 Gateway API와 TLS로 접속 구성하기 (0) | 2026.05.26 |
|---|---|
| Kubernetes kubelet의 컨테이너 로그 로테이션 설정 정리 (0) | 2026.05.25 |
| Kubernetes 로컬 환경에 Private Registry 배포하고 이미지 Push/Pull 설정하기 (0) | 2026.05.20 |
| 로컬 Kubernetes에서 MetalLB로 LoadBalancer IP 할당하기 (0) | 2026.05.20 |
| Gateway API와 Envoy Gateway로 로컬 Kubernetes 서비스 노출하기 (0) | 2026.05.20 |