
이 문서는 EKS (Amazon Elastic Kubernetes Service) 클러스터 환경에서 애플리케이션에 필요한 민감한 시크릿 값(예: 데이터베이스 비밀번호, API 키)과 비민감 환경 변수를 안전하고 자동화된 방식으로 주입하는 전체 과정을 상세히 설명합니다. GitOps 원칙에 따라 모든 설정이 Git에 코드로 관리되며, Argo CD가 이를 클러스터에 자동으로 동기화합니다.
GitHub Actions의 Secret은 CI/CD 파이프라인의 자격 증명으로는 탁월하지만, Kubernetes 클러스터 내에서 실행되는 애플리케이션의 런타임 Secret을 안전하고 동적으로 관리하는 데는 한계가 있습니다.
반면, AWS Secrets Manager + External Secrets Operator 방식은 Kubernetes와 GitOps의 철학에 완벽하게 부합하며, 런타임 Secret의 보안, 자동화, 동기화, 감사 및 운영 편의성 측면에서 훨씬 강력하고 안정적인 솔루션을 제공합니다. 이것이 우리가 이 방식을 선택한 주된 이유입니다.
우리가 구축한 시스템은 다음과 같은 핵심 구성 요소들이 유기적으로 연결되어 작동합니다.
ExternalSecret 리소스를 감지하고, ClusterSecretStore에 정의된 연결 정보를 사용하여 AWS Secrets Manager에서 실제 시크릿 값을 가져옵니다.secrets.properties 파일의 전체 내용을 AWS Secrets Manager의 단일 시크릿(Secret) 값으로 저장합니다. 예를 들어, onthetop/backend/secrets-properties라는 이름으로 시크릿을 생성합니다.aws secretsmanager create-secret \
--name onthetop/backend/secrets-properties \
--secret-string file://./secrets.properties \
--region ap-northeast-2ESO는 AWS Secrets Manager와 Kubernetes 클러스터 간의 시크릿 동기화를 담당하는 핵심 도구입니다.
resource "kubernetes_manifest" "cluster_secret_store" {
manifest = {
apiVersion = "external-secrets.io/v1beta1"
kind = "ClusterSecretStore"
metadata = {
name = "aws-secrets-manager-cluster-store"
}
spec = {
provider = {
aws = {
service = "SecretsManager"
region = "ap-northeast-2"
auth = {
jwt = {
serviceAccountRef = {
name = "external-secrets-sa"
namespace = "external-secrets" # ESO SA가 위치한 네임스페이스
}
}
}
}
}
}
}
}external-secrets 네임스페이스의 external-secrets-sa 서비스 어카운트의 권한을 사용하여 ap-northeast-2 리전의 AWS Secrets Manager에 접근할 수 있도록 합니다.# application-gitops-repo/kubernetes/onthetop-backend/external-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: onthetop-backend-secrets # ESO가 생성할 Kubernetes Secret의 이름
namespace: onthetop-backend # ExternalSecret 및 생성될 Secret이 위치할 네임스페이스
spec:
refreshInterval: "1h" # 1시간마다 AWS Secrets Manager에서 값 동기화
secretStoreRef:
name: aws-secrets-manager-cluster-store # 위에서 정의한 ClusterSecretStore 참조
kind: ClusterSecretStore
target:
name: onthetop-backend-secrets # Kubernetes Secret의 이름 (ExternalSecret의 이름과 동일)
creationPolicy: Owner # ExternalSecret 삭제 시 Kubernetes Secret도 삭제
template:
data:
secrets.properties: "{{ .secrets_properties_file_content }}" # AWS Secrets Manager 값을 secrets.properties 키로 저장
data:
- secretKey: secrets_properties_file_content # AWS Secrets Manager 값의 임시 키
remoteRef:
key: onthetop/backend/secrets-properties # AWS Secrets Manager의 실제 시크릿 이름ExternalSecret은 ESO에게 aws-secrets-manager-cluster-store를 통해 onthetop/backend/secrets-properties 시크릿을 가져와 onthetop-backend-secrets라는 Kubernetes Secret을 onthetop-backend 네임스페이스에 생성하라고 지시합니다.ESO에 의해 생성된 Kubernetes Secret과 ConfigMap은 애플리케이션 Pod에 주입되어 사용됩니다.
volumes와 volumeMounts를 사용하여 Pod의 컨테이너 내부에 파일 형태로 마운트됩니다.# Deployment YAML 내
spec:
template:
spec:
containers:
- name: onthetop-backend
volumeMounts:
- name: secrets-properties-volume
mountPath: "/app/secrets.properties" # 컨테이너 내부 경로
subPath: "secrets.properties" # Secret 내의 키 이름
readOnly: true
volumes:
- name: secrets-properties-volume
secret:
secretName: onthetop-backend-secrets # ESO가 생성한 Secret 이름onthetop-backend-secrets Secret의 secrets.properties 키에 해당하는 내용이 컨테이너 내부의 /app/secrets.properties 파일로 마운트됩니다.JUMP_HOST, BE_VERSION, PORT 등 민감하지 않은 환경 변수나 설정 데이터가 저장되는 Kubernetes의 기본 리소스입니다. Git 리포지토리에 YAML 파일로 정의됩니다.env 섹션에서 valueFrom.configMapKeyRef를 사용하여 컨테이너 환경 변수로 주입됩니다.# application-gitops-repo/kubernetes/onthetop-backend/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: onthetop-backend-config
namespace: onthetop-backend
data:
BE_VERSION: "v2.0.3"
PORT: "8080"# Deployment YAML 내
spec:
template:
spec:
containers:
- name: onthetop-backend
env:
- name: PORT
valueFrom:
configMapKeyRef:
name: onthetop-backend-config # ConfigMap 이름
key: PORT # ConfigMap 내의 키
- name: BE_VERSION
valueFrom:
configMapKeyRef:
name: onthetop-backend-config
key: BE_VERSIONonthetop-backend-config ConfigMap의 PORT와 BE_VERSION 값이 각각 PORT와 BE_VERSION이라는 환경 변수로 컨테이너에 주입됩니다.Secret과 ConfigMap의 데이터를 주입받아 애플리케이션을 실행합니다.# Deployment YAML 내
spec:
template:
spec:
containers:
- name: onthetop-backend
args:
- "--logging.file.name=/logs/backend.log"
- "--spring.config.additional-location=file:/app/secrets.properties" # 마운트된 secrets.properties 파일 사용args를 통해 /app/secrets.properties 경로에 마운트된 파일을 추가 설정 파일로 읽도록 지시합니다.Argo CD는 Git 리포지토리에 정의된 모든 Kubernetes 리소스들을 EKS 클러스터에 자동으로 동기화하는 역할을 합니다.
Namespace, ExternalSecret, ConfigMap, Deployment, Service, Ingress)은 Git 리포지토리(application-gitops-repo)에 저장됩니다.ExternalSecret에는 실제 시크릿 값이 없으므로, Git에 민감 정보가 노출되지 않습니다.argocd-config-repo)에 Application 리소스를 정의합니다. 이 Application 리소스는 Argo CD에게 "어떤 Git 리포지토리의 어떤 경로를 모니터링하여, 어떤 클러스터의 어떤 네임스페이스에 배포할지"를 알려줍니다.# argocd-config-repo/applications/onthetop-backend.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: onthetop-backend
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/your-org/application-gitops-repo.git
targetRevision: HEAD
path: kubernetes/onthetop-backend # YAML 파일들이 있는 경로
destination:
server: https://kubernetes.default.svc
namespace: onthetop-backend # 배포될 네임스페이스
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true # 네임스페이스 자동 생성application-gitops-repo를 지속적으로 모니터링합니다.Namespace, ConfigMap, ExternalSecret, Deployment, Service, Ingress 등이 순차적으로 생성/업데이트됩니다.ExternalSecret이 생성되면 ESO가 작동하여 Kubernetes Secret을 만들고, Deployment는 이 Secret과 ConfigMap을 참조하여 Pod를 실행합니다.이러한 통합된 접근 방식을 통해, onthetop-backend 애플리케이션은 AWS Secrets Manager에 저장된 민감한 시크릿 값과 ConfigMap에 정의된 비민감 환경 변수를 안전하고 효율적으로 주입받아 EKS 클러스터에 배포됩니다. 모든 설정은 Git에 코드로 관리되므로, 배포의 자동화, 일관성, 재현성 및 보안이 크게 향상됩니다.