Pod가 Running 상태라고 해서 운영 가능한 상태는 아닙니다. 진짜 운영 가능한 애플리케이션은 환경별 설정이 분리되어 있고, 민감 정보가 코드 밖에서 관리되며, 외부 트래픽 진입 경로가 설계되어 있어야 합니다. 이번 글에서는 그 세 가지를 담당하는 ConfigMap, Secret, Ingress를 정리합니다.
코드에 설정값을 직접 박아 넣으면 두 가지 문제가 생깁니다.
보안 관점
운영 관점
12-Factor App 원칙: 설정은 환경에서 주입하고, 코드와 분리해야 합니다.
기준은 하나입니다. "이 값이 공개되면 보안 사고가 나는가?"
| 종류 | 용도 | 예시 |
|---|---|---|
| ConfigMap | 노출되어도 큰 문제 없는 비민감 설정 | APP_ENV, LOG_LEVEL, PUBLIC_API_URL |
| Secret | 절대 노출되면 안 되는 민감 설정 | DB_PASSWORD, API_KEY, JWT_SECRET |
apiVersion: v1
kind: ConfigMap
metadata:
name: team-board-config
namespace: default
data:
APP_ENV: "production"
LOG_LEVEL: "info"
핵심:
data필드에 키-값 쌍을 정의합니다. 모든 값은 문자열로 저장되므로 숫자도 따옴표로 감쌉니다.
| 방식 | 언제 쓰나 | 특징 |
|---|---|---|
| envFrom / env | process.env, os.getenv()로 읽을 때 | Pod 재시작 시에만 새 값 반영 |
| volume 마운트 | nginx.conf처럼 파일 형태가 필요할 때 | ConfigMap 변경 시 파일 자동 갱신 |
kubectl get configmap team-board-config
kubectl describe configmap team-board-config
kubectl exec -it [pod-name] -- env | grep APP_ENV
kubectl rollout restart deployment/team-board-app
Secret의 data 필드 값이 알 수 없는 문자로 보여서 암호화된 것으로 오해하기 쉽습니다.
cGFzc3dvcmQ= 이건 password를 base64로 인코딩한 것입니다. 누구나 즉시 복호화할 수 있습니다.
echo "cGFzc3dvcmQ=" | base64 -d # → password
Secret이 안전한 이유는 base64가 아니라, etcd 암호화 설정, RBAC 접근 제어, 네트워크 격리 때문입니다.
apiVersion: v1
kind: Secret
metadata:
name: team-board-db-secret
namespace: default
type: Opaque
stringData:
DB_HOST: "postgres-service"
DB_USER: "boarduser"
DB_PASSWORD: "s3cur3P@ss!"
DB_NAME: "teamboard"
stringData는 평문으로 입력하면 Kubernetes가 자동으로 base64로 저장합니다. 단, 이 파일을 Git에 올리면 절대 안 됩니다.
Service만 쓰면 서비스마다 별도 포트(30001, 30002…)가 필요하고 도메인 기반 라우팅이 불가능합니다. Ingress를 추가하면 하나의 진입점(80/443)으로 통합할 수 있습니다.
| 방식 | 사용 시점 | 예시 |
|---|---|---|
| host 기반 | 서브도메인으로 서비스를 나눌 때 | app.example.com → team-board-service |
| path 기반 | 하나의 도메인 아래 여러 서비스를 운영할 때 | example.com/api → api-service |
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: team-board-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: team-board.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: app-service
port:
number: 8080
Ingress 리소스는 라우팅 규칙을 선언하는 설계도일 뿐입니다. 실제로 동작하려면 Controller가 필요합니다.
# minikube 환경
minikube addons enable ingress
운영 환경에서는 nginx-ingress-controller, Traefik, AWS ALB Ingress Controller 중 환경에 맞는 것을 선택합니다.
| 리소스 | 역할 |
|---|---|
| ConfigMap | 비민감 설정을 이미지 밖으로 분리, 재빌드 없이 설정 변경 가능 |
| Secret | 민감 정보 보호, base64 인코딩(암호화 아님) + RBAC으로 접근 제어 |
| Ingress | 외부 트래픽 단일 진입점, host/path 기반 라우팅, TLS 한 곳에서 관리 |
설정 분리는 단순한 코드 정리가 아닙니다. 동일한 이미지를 여러 환경에 재사용하고, 민감 정보를 코드 바깥에서 관리하고, 외부 트래픽 흐름을 선언적으로 설계하는 것이 운영 가능한 애플리케이션의 기준입니다.
| 분산 시스템의 핵심: 클러스터와 아키텍처, 초보 개발자도 쉽게 이해하기 (0) | 2026.04.27 |
|---|---|
| 쿠버네티스(Kubernetes) 핵심 이해: 아키텍처와 클러스터 기초 완벽 가이드 (0) | 2026.04.26 |
| Docker 입문 완전정리: 이미지 한 번에 이해하기 (0) | 2026.04.23 |
| Docker 입문자를 위한 핵심 정리: 이미지, 컨테이너, docker run까지 (1) | 2026.04.22 |
| DevOps 입문자가 먼저 배워야 할 Linux, Shell, Git 정리 (1) | 2026.04.22 |