본문 바로가기
K8S

Kubernetes에서 애플리케이션 설정 우선순위 이해하기

by Rainbound-IT 2025. 10. 23.
반응형

목차

     

     

     

     

    ConfigMap, Secret, 그리고 내부 설정 중 무엇이 이길까?

    Kubernetes에서 애플리케이션을 배포하다 보면,

    앱 내부 설정값이 우선일까, ConfigMap/Secret이 우선일까?”라는 의문이 자주 생깁니다.

    특히 운영 중인 서비스의 환경설정이 기대와 다르게 동작할 때,

    이 우선순위를 정확히 이해하고 있지 않으면 디버깅이 어렵습니다.

    이 글에서는 Kubernetes가 실제로 설정값을 어떻게 주입하고,

    최종적으로 어떤 값이 적용되는지를 프레임워크별로 정리해보겠습니다.


    1️⃣ Kubernetes는 ‘우선순위’를 결정하지 않는다

    먼저 중요한 사실 하나:

    Kubernetes는 단지 환경 변수나 파일 형태로 설정을 주입할 뿐,

    어떤 값이 “최종적으로 우선”인지는 애플리케이션의 설정 로더가 결정합니다.

    즉, ConfigMap이나 Secret은 그저 전달자입니다.

    Pod에 들어간 뒤 실제로 어떤 값이 사용될지는

    Spring Boot, Node.js, .NET, Django 등 프레임워크가 정의한 로딩 순서에 따라 달라집니다.


    2️⃣ 일반적인 우선순위 구조 (12-Factor 원칙 기반)

    대부분의 현대 애플리케이션은 12-Factor App 원칙을 따릅니다.

    이에 따르면 설정값의 우선순위는 다음과 같습니다:

    (최우선)   커맨드라인 인자
        ↑      환경변수 (ConfigMap / Secret로 주입된 값)
        ↑      외부 설정 파일 (마운트된 ConfigMap/Secret 파일)
    (최하)     애플리케이션 내부 기본값 (코드에 내장된 설정)
    

    즉, ConfigMap/Secret을 통해 주입된 환경변수는 내부 설정(application.yml, .env 등)보다 항상 우선합니다.


    3️⃣ 프레임워크별 실제 우선순위 비교

     

    프레임워크  우선순위 요약  주요 포인트
    Spring Boot Command-line > System properties > Environment variables > External config files > Internal application.yml ConfigMap/Secret의 env 값이 내부 application.yml을 덮음
    .NET Core appsettings.json → appsettings.{ENV}.json → Environment variables → Command-line 환경변수가 JSON 설정보다 우선
    Node.js (dotenv 사용 시) 기본값 < .env < K8s 환경변수 < 커맨드라인 이미 존재하는 환경변수는 .env로 덮이지 않음
    Python (Django/FastAPI) 코드 기본값 < 파일(.env/settings.py) < 환경변수 < CLI pydantic-settings/django-environ 기준 env가 최종 우선

    요점:

    거의 모든 프레임워크에서 “환경변수(env)”는 내부 설정보다 상위에 존재합니다.

    즉, ConfigMap 또는 Secret으로 환경변수를 주입했다면,

    그 값이 내부 설정을 덮어씁니다.


    4️⃣ 실무에서 자주 혼동하는 케이스

    🧩 예시 1: ConfigMap과 Secret이 모두 같은 key를 가진 경우

    envFrom:
      - configMapRef:
          name: my-config
      - secretRef:
          name: my-secret
    
    

    → 같은 key가 있다면 **나중에 선언된 것(Secret)**이 환경변수로 등록됩니다.

    Kubernetes가 결정하는 유일한 “순서”는 바로 이 envFrom 선언 순서입니다.


    🧩 예시 2: 애플리케이션 내부 설정이 덮이지 않는 경우

    Spring Boot 기준:

    spring:
      datasource:
        url: jdbc:mysql://localhost/dev
    
    

    위 설정이 JAR 안에 baked-in 되어 있어도,

    Pod 환경변수로 SPRING_DATASOURCE_URL이 들어가면 그 값이 자동으로 override 됩니다.

    만약 반대로 application.yml 값이 그대로 적용된다면,

    • 환경변수 이름이 잘못 매핑되었거나 (. → _, 대문자 변환 등)
    • ConfigMap이 env로 주입되지 않았거나
    • 프레임워크의 설정 로딩 순서가 커스터마이징되어 있을 가능성이 있습니다.

    5️⃣ 실전에서 설정 충돌 방지하는 3가지 팁

    1️⃣ 환경변수를 진리로 삼기

    • 앱이 읽는 모든 외부 설정은 환경변수 기준으로 동작하게 설계
    • Secret은 파일로 마운트하더라도, 경로만 환경변수로 전달

    2️⃣ 시작 로그로 최종 설정 확인

    • kubectl exec로 컨테이너 내부 env를 확인하거나
    • 앱 부트 시점에 주요 설정값(비밀번호 제외)을 로깅

    3️⃣ 명시적 override 규칙 문서화

    • 팀 내에서 “무엇이 내부 설정이고, 무엇이 환경변수인지” 정리
    • staging/prod 차이를 ConfigMap/Secret에서만 관리하면 일관성 확보

    6️⃣ 결론 요약

     

    구분  우선순위  설명 
    커맨드라인 인자 ⭐ 최우선 빠른 테스트나 임시 수정에 유용
    환경변수 (ConfigMap/Secret) ✅ 기본 우선 대부분의 프레임워크에서 내부 설정보다 상위
    마운트된 설정 파일 ⚙️ 중간 로딩 순서에 따라 env보다 낮을 수도
    애플리케이션 내부 기본값 💤 최하 코드에 내장된 기본값

    결론:

    “ConfigMap/Secret으로 주입된 환경변수”가

    “application 내부 설정”보다 항상 우선이다.

    하지만 “어떤 방식으로 주입하느냐”와 “프레임워크의 설정 로딩 순서”에 따라

    실제 결과는 달라질 수 있다. 따라서 환경변수를 표준 인터페이스로 삼는 구조

    운영에서 가장 안전하고 예측 가능하다.

     

    반응형

    댓글