M5. ConfigMap·Secret·환경변수 주입
1. 왜 필요한가
섹션 제목: “1. 왜 필요한가”NKS로 옮길 web-app, api-service, ai-service가 환경별 주소·log level을 image에
굽거나 API token을 manifest에 적으면 같은 image를 재사용하기 어렵고 유출 범위도 커집니다.
ConfigMap과 Secret의 역할, env 주입 시점, 변경 후 rollout 필요 여부를 구분해야 AI가 제안한
배포 변경을 안전하게 리뷰할 수 있습니다.
개념 정의의 정본은 Kubernetes Basics와
Secrets Management입니다. 원본 경로는 각각
content/topics/L5/kubernetes-basics.mdx, content/topics/L3/secrets-management.mdx이며, 이
모듈은 M4의 안정된 Service 경로 위에서 설정·민감값을 process env로 전달하는 실행 경계만
검증합니다.
2. 핵심 개념
섹션 제목: “2. 핵심 개념”flowchart LR Image["동일한 container image"] --> Template["Deployment Pod template"] CM["ConfigMap: 비민감 설정"] --> Ref["configMapKeyRef"] Secret["Secret: 민감값 전달 객체"] --> SRef["secretKeyRef"] Ref --> Template SRef --> Template Template -->|"Pod 시작 시 kubelet이 주입"| Env["process env snapshot"] Source["ConfigMap/Secret 값 변경"] -->|"실행 중 env는 그대로"| Stale["기존 Pod: old value"] Source --> Restart["rollout restart"] Restart --> NewPod["새 Pod: latest value"]
| 구분 | 담을 값 예시 | 이 랩에서 보는 증거 |
|---|---|---|
| ConfigMap | APP_MODE, LOG_LEVEL | 평문 설정과 configMapKeyRef |
| Secret | API token, DB password | 값은 출력하지 않고 key·길이·주입 여부만 확인 |
env[].valueFrom | 필요한 key만 다른 env 이름으로 주입 | source object·key를 명시적으로 리뷰 |
envFrom | object의 유효한 key를 한꺼번에 주입 | 편하지만 충돌·불필요한 값 노출 범위가 커짐 |
| 실행 중 process env | Pod 시작 시 받은 snapshot | source 변경 뒤에도 old value 유지 |
| rollout 뒤 새 process env | 최신 source로 만든 새 snapshot | Pod 교체와 최신 revision 확인 |
ConfigMap은 비민감 설정을 image와 분리하는 API object이며 secrecy나 encryption을 제공하지
않습니다. Secret은 민감 데이터를 전달하기 위한 별도 object지만 data의 base64는 encoding일
뿐 encryption이 아닙니다. Secret을 쓴다는 사실만으로 저장 시 암호화, 최소 RBAC, audit,
rotation과 소비자 갱신이 자동 완성되지는 않습니다.
환경변수로 주입한 ConfigMap·Secret 값은 process가 시작할 때 정해집니다. source object를
바꿔도 기존 process env는 바뀌지 않으며, 새 Pod가 생기면 그 Pod만 최신 값을 받을 수 있어
의도하지 않은 old/new 혼합 상태가 생길 수 있습니다. 이 모듈은 명시적인 rollout과 검증으로
한 version에 수렴시킵니다. Volume projection의 갱신·subPath 예외와 application hot reload는
심화 범위입니다.
flowchart LR Store["Infisical project"] --> Identity["Machine identity + auth"] Identity --> Operator["Infisical Operator controller"] CRD["InfisicalStaticSecret CRD"] --> Operator Operator --> Native["namespace의 Kubernetes Secret"] Native --> Pod["Pod env 또는 volume"] Update["rotation / sync"] --> Operator Operator --> Reload["Deployment reload 정책"]
Infisical Operator를 사용해도 최종 Kubernetes Secret의 namespace, RBAC, Pod 전달 방식과 reload 정책은 남습니다. 외부 저장소가 source of truth인지, native Secret의 lifecycle owner가 누구인지, sync 실패 때 기존 값 유지와 rollout을 어떻게 관찰할지 함께 결정해야 합니다.
시점 의존 설명은 2026-07-15에 다음 공식 1차 자료로 확인했습니다.
- ConfigMaps: 비민감 데이터,
configMapKeyRef·envFrom, env 갱신에는 Pod restart 필요 - Secrets: Secret 사용 경계,
secretKeyRef, base64가 confidentiality를 제공하지 않는다는 주의 - Updating Configuration via a ConfigMap: 기존 env 유지, rollout 뒤 최신 값, rollout 전 old/new 혼합 가능성
- Infisical Kubernetes Operator:
v1beta1 CRD,
InfisicalStaticSecret, sync와 Deployment reload 기능·지원 범위
현재 Infisical 공식 문서가 표시하는 Operator 지원 Kubernetes minor는 1.29~1.33이며 NKS는
검증된 배포판 목록에 없습니다. 이 랩의 K3s 1.36.2에 Operator를 설치하지 않고
official-doc-only로만 다룹니다. M7에서 Helm과 release rollback을 학습한 뒤에도 실제 도입은
승인된 non-production NKS에서 Kubernetes compatibility, namespace-scoped RBAC, 인증 방식,
sync·reload failure를 별도로 검증해야 합니다.
3. 직관 비유
섹션 제목: “3. 직관 비유”| 개념 | 비유 | 비유의 경계 |
|---|---|---|
| ConfigMap | 제품과 분리해 갈아 끼우는 비민감 설정표 | 비밀 금고가 아니며 읽기 권한 통제는 별도입니다. |
| Secret | 열람자를 제한해야 하는 봉투 | base64 표기는 자물쇠가 아니고 저장 암호화도 보장하지 않습니다. |
| process env 주입 | 출발할 때 한 번 인쇄된 탑승 정보 | 원본을 고쳐도 이미 출발한 process에는 다시 인쇄되지 않습니다. |
| Infisical Operator | 중앙 금고 값을 namespace 봉투로 동기화하는 담당자 | downstream Secret·RBAC·reload 판단까지 없애지 않습니다. |
4. 핸즈온 랩
섹션 제목: “4. 핸즈온 랩”검증 환경
섹션 제목: “검증 환경”| 항목 | 검증값 |
|---|---|
| 기준일 | 2026-07-15 |
| host | macOS arm64 |
| Docker client / engine | 29.6.1 / 29.6.1 |
| k3d | 5.9.0 |
| K3s image / API server | rancher/k3s:v1.36.2-k3s1 / v1.36.2+k3s1 |
| kubectl | 1.36.1 |
| Helm | 4.2.3 — 이 모듈에서는 사용하지 않음 |
| container image | busybox:1.37.0 + Setup의 고정 multi-platform digest |
| evidence 환경 | local-cluster; 고정 context + k8s-wb-m5-<UTC run ID> |
모든 shell 명령 묶음은 executed-local입니다. 실제 production credential, NKS encryption at rest,
RBAC·audit 설정과 Infisical 설치·연동은 승인된 provider 환경이 없으므로 각각 excluded 또는
official-doc-only이며 예상 출력을 제시하지 않습니다.
사전 조건
섹션 제목: “사전 조건”- 저장소 root에서 실행하며 M0~M4를 완료한 상태여야 합니다.
- Docker Desktop과 M2의
cs-study-workbookcluster가 실행 중이어야 합니다. - 모든 workload API 명령은
--context k3d-cs-study-workbook과 고유 namespace를 명시합니다. - fixture token은 실행마다 host의 권한 제한 파일에서 생성하고 값 자체를 stdout, evidence, manifest에 출력하지 않습니다. 실제 credential이 아닙니다.
- 예상 소요 시간은 95분입니다.
Setup
섹션 제목: “Setup”ConfigMap·Secret과 Deployment 만들기
섹션 제목: “ConfigMap·Secret과 Deployment 만들기”Secret 값은 명령행 literal이나 YAML에 적지 않습니다. 임시 파일 권한을 600으로 제한하고
--from-file로 전송한 직후 host 파일을 지웁니다.
set -euo pipefailrm -rf /tmp/k8s-wb-m5mkdir -p /tmp/k8s-wb-m5chmod 700 /tmp/k8s-wb-m5node automation/k8s-workbook/preflight.mjs --require-clustertest "$(kubectl config current-context)" = "k3d-cs-study-workbook"NS="k8s-wb-m5-$(date -u +%Y%m%d%H%M%S)"printf '%s' "$NS" > /tmp/k8s-wb-m5/namespaceif kubectl --context k3d-cs-study-workbook get namespace "$NS" >/dev/null 2>&1; then echo "namespace collision: $NS" >&2 exit 1fikubectl --context k3d-cs-study-workbook create namespace "$NS"kubectl --context k3d-cs-study-workbook -n "$NS" create configmap app-runtime \ --from-literal=APP_MODE=preview \ --from-literal=LOG_LEVEL=info \ --dry-run=client -o yaml \ | kubectl --context k3d-cs-study-workbook -n "$NS" apply -f -umask 077trap 'rm -f /tmp/k8s-wb-m5/api-token' EXITopenssl rand -hex 16 | tr -d '\n' > /tmp/k8s-wb-m5/api-tokentest "$(wc -c < /tmp/k8s-wb-m5/api-token | tr -d ' ')" = "32"kubectl --context k3d-cs-study-workbook -n "$NS" create secret generic app-credentials \ --from-file=API_TOKEN=/tmp/k8s-wb-m5/api-token \ --from-literal=TOKEN_REVISION=rev1 \ --dry-run=client -o yaml \ | kubectl --context k3d-cs-study-workbook -n "$NS" apply -f -rm -f /tmp/k8s-wb-m5/api-tokentrap - EXITkubectl --context k3d-cs-study-workbook -n "$NS" apply -f - <<'YAML'apiVersion: apps/v1kind: Deploymentmetadata: name: api-servicespec: replicas: 1 selector: matchLabels: app: api-service template: metadata: labels: app: api-service spec: terminationGracePeriodSeconds: 3 containers: - name: app image: busybox:1.37.0@sha256:9532d8c39891ca2ecde4d30d7710e01fb739c87a8b9299685c63704296b16028 imagePullPolicy: IfNotPresent command: ["sh", "-c", "sleep 3600"] env: - name: APP_MODE valueFrom: configMapKeyRef: name: app-runtime key: APP_MODE - name: LOG_LEVEL valueFrom: configMapKeyRef: name: app-runtime key: LOG_LEVEL - name: API_TOKEN valueFrom: secretKeyRef: name: app-credentials key: API_TOKEN - name: TOKEN_REVISION valueFrom: secretKeyRef: name: app-credentials key: TOKEN_REVISIONYAMLkubectl --context k3d-cs-study-workbook -n "$NS" \ rollout status deployment/api-service --timeout=90s >/dev/nulltest ! -e /tmp/k8s-wb-m5/api-tokenecho 'fixture=configmap,secret,deployment ready=true token_file=absent'예상 출력:
PASS platform: darwin/arm64PASS architecture: arm64PASS docker-cli: v29.6.1PASS docker-engine: v29.6.1PASS k3d: v5.9.0PASS kubectl-skew: v1.36.1PASS helm: v4.2.3PASS context: k3d-cs-study-workbookPASS kubernetes-server: v1.36.2+k3s1namespace/k8s-wb-m5-<UTC 14자리 run ID> createdconfigmap/app-runtime createdsecret/app-credentials createddeployment.apps/api-service createdfixture=configmap,secret,deployment ready=true token_file=absenthost architecture, Docker patch version과 namespace run ID는 변동 필드입니다. token 값은 변동값이지만 출력하지 않으며 길이와 전달 성공만 확인합니다.
Lab 1 — source reference와 안전한 주입 증거 확인하기
섹션 제목: “Lab 1 — source reference와 안전한 주입 증거 확인하기”set -euo pipefailtest "$(kubectl config current-context)" = "k3d-cs-study-workbook"NS="$(cat /tmp/k8s-wb-m5/namespace)"MODE="$(kubectl --context k3d-cs-study-workbook -n "$NS" get configmap app-runtime \ -o jsonpath='{.data.APP_MODE}')"LEVEL="$(kubectl --context k3d-cs-study-workbook -n "$NS" get configmap app-runtime \ -o jsonpath='{.data.LOG_LEVEL}')"SECRET_TYPE="$(kubectl --context k3d-cs-study-workbook -n "$NS" get secret app-credentials \ -o jsonpath='{.type}')"TOKEN_BYTES="$(kubectl --context k3d-cs-study-workbook -n "$NS" get secret app-credentials \ -o jsonpath='{.data.API_TOKEN}' | base64 -d | wc -c | tr -d ' ')"test "$TOKEN_BYTES" = "32"POD="$(kubectl --context k3d-cs-study-workbook -n "$NS" get pod -l app=api-service \ -o jsonpath='{.items[0].metadata.name}')"kubectl --context k3d-cs-study-workbook -n "$NS" exec "$POD" -- sh -c ' test "$APP_MODE" = preview test "$LOG_LEVEL" = info test "$TOKEN_REVISION" = rev1 test "${#API_TOKEN}" = 32 printf "process_env mode=%s log_level=%s token_revision=%s token_present=true token_length=%s\n" \ "$APP_MODE" "$LOG_LEVEL" "$TOKEN_REVISION" "${#API_TOKEN}"'printf 'configmap mode=%s log_level=%s\n' "$MODE" "$LEVEL"printf 'secret type=%s keys=API_TOKEN,TOKEN_REVISION token_length=%s value_printed=false\n' \ "$SECRET_TYPE" "$TOKEN_BYTES"printf 'references=configMapKeyRef,secretKeyRef explicit=true\n'예상 출력:
process_env mode=preview log_level=info token_revision=rev1 token_present=true token_length=32configmap mode=preview log_level=infosecret type=Opaque keys=API_TOKEN,TOKEN_REVISION token_length=32 value_printed=falsereferences=configMapKeyRef,secretKeyRef explicit=trueSecret의 base64를 decode해 화면에 출력하지 않습니다. byte count는 fixture 전달 여부의 증거이지 실제 credential을 검증하는 방식이 아닙니다.
Lab 2 — source를 바꿔도 기존 process env가 그대로인지 보기
섹션 제목: “Lab 2 — source를 바꿔도 기존 process env가 그대로인지 보기”set -euo pipefailtest "$(kubectl config current-context)" = "k3d-cs-study-workbook"NS="$(cat /tmp/k8s-wb-m5/namespace)"OLD_POD="$(kubectl --context k3d-cs-study-workbook -n "$NS" get pod -l app=api-service \ -o jsonpath='{.items[0].metadata.name}')"printf '%s' "$OLD_POD" > /tmp/k8s-wb-m5/pod-beforekubectl --context k3d-cs-study-workbook -n "$NS" patch configmap app-runtime \ --type=merge -p '{"data":{"APP_MODE":"live"}}' >/dev/nullumask 077trap 'rm -f /tmp/k8s-wb-m5/api-token' EXITopenssl rand -hex 16 | tr -d '\n' > /tmp/k8s-wb-m5/api-tokenkubectl --context k3d-cs-study-workbook -n "$NS" create secret generic app-credentials \ --from-file=API_TOKEN=/tmp/k8s-wb-m5/api-token \ --from-literal=TOKEN_REVISION=rev2 \ --dry-run=client -o yaml \ | kubectl --context k3d-cs-study-workbook -n "$NS" apply -f - >/dev/nullrm -f /tmp/k8s-wb-m5/api-tokentrap - EXITOBJECT_MODE="$(kubectl --context k3d-cs-study-workbook -n "$NS" get configmap app-runtime \ -o jsonpath='{.data.APP_MODE}')"OBJECT_REVISION="$(kubectl --context k3d-cs-study-workbook -n "$NS" get secret app-credentials \ -o jsonpath='{.data.TOKEN_REVISION}' | base64 -d)"test "$OBJECT_MODE" = "live"test "$OBJECT_REVISION" = "rev2"kubectl --context k3d-cs-study-workbook -n "$NS" exec "$OLD_POD" -- sh -c ' test "$APP_MODE" = preview test "$TOKEN_REVISION" = rev1 printf "running_pod mode=%s token_revision=%s stale=true\n" "$APP_MODE" "$TOKEN_REVISION"'printf 'source_objects mode=%s token_revision=%s updated=true\n' \ "$OBJECT_MODE" "$OBJECT_REVISION"예상 출력:
running_pod mode=preview token_revision=rev1 stale=truesource_objects mode=live token_revision=rev2 updated=truesource object와 process env가 동시에 다른 값을 가진 실측 결과입니다. 이 상태에서 replica를 늘리면 새 Pod만 최신 값을 받아 old/new 설정이 섞일 수 있습니다.
Lab 3 — rollout으로 새 env snapshot에 수렴시키기
섹션 제목: “Lab 3 — rollout으로 새 env snapshot에 수렴시키기”set -euo pipefailtest "$(kubectl config current-context)" = "k3d-cs-study-workbook"NS="$(cat /tmp/k8s-wb-m5/namespace)"OLD_POD="$(cat /tmp/k8s-wb-m5/pod-before)"kubectl --context k3d-cs-study-workbook -n "$NS" \ rollout restart deployment/api-servicekubectl --context k3d-cs-study-workbook -n "$NS" \ rollout status deployment/api-service --timeout=90s >/dev/nullkubectl --context k3d-cs-study-workbook -n "$NS" \ wait --for=delete "pod/$OLD_POD" --timeout=90s >/dev/nullPOD_COUNT="$(kubectl --context k3d-cs-study-workbook -n "$NS" get pod -l app=api-service \ -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | sed '/^$/d' | wc -l | tr -d ' ')"test "$POD_COUNT" = "1"NEW_POD="$(kubectl --context k3d-cs-study-workbook -n "$NS" get pod -l app=api-service \ -o jsonpath='{.items[0].metadata.name}')"test "$NEW_POD" != "$OLD_POD"kubectl --context k3d-cs-study-workbook -n "$NS" exec "$NEW_POD" -- sh -c ' test "$APP_MODE" = live test "$LOG_LEVEL" = info test "$TOKEN_REVISION" = rev2 test "${#API_TOKEN}" = 32 printf "new_process mode=%s log_level=%s token_revision=%s token_present=true token_length=%s\n" \ "$APP_MODE" "$LOG_LEVEL" "$TOKEN_REVISION" "${#API_TOKEN}"'printf 'pod_replaced old=%s new=%s latest_snapshot=true\n' "$OLD_POD" "$NEW_POD"예상 출력:
deployment.apps/api-service restartednew_process mode=live log_level=info token_revision=rev2 token_present=true token_length=32pod_replaced old=api-service-<이전 hash>-<suffix> new=api-service-<새 hash>-<suffix> latest_snapshot=truePod 이름은 변동값입니다. source 변경 자체가 아니라 Pod template annotation을 바꾼 rollout이 새 process를 만들었다는 점을 구분합니다.
Lab 4 — 없는 key로 CreateContainerConfigError 재현하기
섹션 제목: “Lab 4 — 없는 key로 CreateContainerConfigError 재현하기”optional: false가 기본이므로 typo를 조용히 빈 문자열로 바꾸지 않고 container 시작 전에
막습니다.
set -euo pipefailtest "$(kubectl config current-context)" = "k3d-cs-study-workbook"NS="$(cat /tmp/k8s-wb-m5/namespace)"kubectl --context k3d-cs-study-workbook -n "$NS" apply -f - <<'YAML'apiVersion: v1kind: Podmetadata: name: broken-envspec: terminationGracePeriodSeconds: 3 containers: - name: app image: busybox:1.37.0@sha256:9532d8c39891ca2ecde4d30d7710e01fb739c87a8b9299685c63704296b16028 imagePullPolicy: IfNotPresent command: ["sh", "-c", "sleep 3600"] env: - name: APP_MODE valueFrom: configMapKeyRef: name: app-runtime key: DOES_NOT_EXISTYAMLREASON=""for _ in $(seq 1 30); do REASON="$(kubectl --context k3d-cs-study-workbook -n "$NS" get pod broken-env \ -o jsonpath='{.status.containerStatuses[0].state.waiting.reason}')" test "$REASON" = "CreateContainerConfigError" && break sleep 1donetest "$REASON" = "CreateContainerConfigError"set +ekubectl --context k3d-cs-study-workbook -n "$NS" \ wait --for=condition=Ready pod/broken-env --timeout=5s \ > /tmp/k8s-wb-m5/broken-ready.log 2>&1READY_EXIT=$?set -etest "$READY_EXIT" = "1"grep -q 'timed out waiting for the condition' /tmp/k8s-wb-m5/broken-ready.logprintf 'pod=broken-env reason=%s ready=false exit=%s\n' "$REASON" "$READY_EXIT"exit 1예상 출력과 exit code:
pod/broken-env createdpod=broken-env reason=CreateContainerConfigError ready=false exit=1전체 예상 exit code는 1입니다. image pull이나 application crash 전에 kubelet이 참조 key를
찾지 못해 container 구성을 만들지 못한 상태입니다.
복구 — typo를 실제 key로 고쳐 새 Pod 만들기
섹션 제목: “복구 — typo를 실제 key로 고쳐 새 Pod 만들기”Pod의 핵심 container env는 in-place 수정하지 않습니다. 실패한 Pod를 지우고 올바른 spec으로 다시 만듭니다.
set -euo pipefailtest "$(kubectl config current-context)" = "k3d-cs-study-workbook"NS="$(cat /tmp/k8s-wb-m5/namespace)"kubectl --context k3d-cs-study-workbook -n "$NS" delete pod broken-env --wait=true >/dev/nullkubectl --context k3d-cs-study-workbook -n "$NS" apply -f - <<'YAML'apiVersion: v1kind: Podmetadata: name: broken-envspec: terminationGracePeriodSeconds: 3 containers: - name: app image: busybox:1.37.0@sha256:9532d8c39891ca2ecde4d30d7710e01fb739c87a8b9299685c63704296b16028 imagePullPolicy: IfNotPresent command: ["sh", "-c", "sleep 3600"] env: - name: APP_MODE valueFrom: configMapKeyRef: name: app-runtime key: APP_MODEYAMLkubectl --context k3d-cs-study-workbook -n "$NS" \ wait --for=condition=Ready pod/broken-env --timeout=90s >/dev/nullMODE="$(kubectl --context k3d-cs-study-workbook -n "$NS" exec broken-env -- \ sh -c 'printf %s "$APP_MODE"')"test "$MODE" = "live"printf 'recovery=correct-key pod=Ready mode=%s\n' "$MODE"예상 출력:
pod/broken-env createdrecovery=correct-key pod=Ready mode=liveCleanup
섹션 제목: “Cleanup”Namespace와 host fixture 제거하기
섹션 제목: “Namespace와 host fixture 제거하기”set -euo pipefailtest "$(kubectl config current-context)" = "k3d-cs-study-workbook"NS="$(cat /tmp/k8s-wb-m5/namespace)"kubectl --context k3d-cs-study-workbook delete namespace "$NS" --wait=false >/dev/nullkubectl --context k3d-cs-study-workbook wait --for=delete "namespace/$NS" --timeout=120s >/dev/nullif kubectl --context k3d-cs-study-workbook get namespace "$NS" >/dev/null 2>&1; then echo "cleanup failed: namespace remains" >&2 exit 1firm -rf /tmp/k8s-wb-m5test ! -e /tmp/k8s-wb-m5READY_NODES="$(kubectl --context k3d-cs-study-workbook get nodes --no-headers \ | awk '$2 == "Ready" {count++} END {print count+0}')"test "$READY_NODES" = "2"printf 'cleanup namespace=0 fixture=0 secret_files=0 nodes_ready=%s cluster_retained=true\n' \ "$READY_NODES"예상 출력:
cleanup namespace=0 fixture=0 secret_files=0 nodes_ready=2 cluster_retained=true5. 관찰 포인트
섹션 제목: “5. 관찰 포인트”| 실행 뒤 | 실제 변화 | 운영 판단 |
|---|---|---|
| ConfigMap·Secret 생성 | 설정 object와 민감값 전달 object가 image 밖에 존재 | object 종류만으로 RBAC·암호화·rotation이 끝나지 않습니다. |
| 명시적 key 주입 | 필요한 4개 env만 process에 존재 | envFrom보다 review할 노출 범위가 작습니다. |
| source object 갱신 | object는 live/rev2, 기존 process는 preview/rev1 | running env는 자동 갱신되지 않습니다. |
| rollout restart | Pod 교체 뒤 live/rev2로 수렴 | 실제 process 값을 안전한 marker로 확인합니다. |
| 없는 ConfigMap key | CreateContainerConfigError, Ready 실패 | image나 app log보다 object name·key·event를 먼저 봅니다. |
| cleanup | M5 object·host token file 0, 공유 cluster 유지 | 민감 fixture를 host에도 남기지 않습니다. |
6. 셀프체크 Q&A
섹션 제목: “6. 셀프체크 Q&A”Q1. APP_MODE를 바꾼 뒤 replica 3개 중 1개만 새 값입니다. ConfigMap이 고장난 걸까요?
섹션 제목: “Q1. APP_MODE를 바꾼 뒤 replica 3개 중 1개만 새 값입니다. ConfigMap이 고장난 걸까요?”먼저 각 Pod의 생성 시각과 실제 env marker를 비교합니다. ConfigMap env는 기존 process에 자동 반영되지 않으므로 우연히 새로 생긴 Pod만 최신 값을 받았을 가능성이 큽니다. Pod template에 의도한 version을 반영하거나 승인된 rollout을 수행하고, 모든 replica가 같은 marker에 수렴했는지 검증합니다.
Q2. AI가 “Secret도 base64로 보이니 API token을 ConfigMap에 넣어도 같다”고 제안했습니다. 받아들여도 될까요?
섹션 제목: “Q2. AI가 “Secret도 base64로 보이니 API token을 ConfigMap에 넣어도 같다”고 제안했습니다. 받아들여도 될까요?”안 됩니다. base64가 encryption이 아니라는 지적과 ConfigMap을 쓰자는 결론은 별개입니다. 민감값은 Secret 또는 승인된 외부 secret delivery 경로로 분리하고, 최소 RBAC·저장 시 암호화, audit·rotation·소비자 갱신을 함께 검토합니다. Secret 값이나 decoded 결과를 PR·terminal log에 남기지 않습니다.
Q3. Infisical Operator를 바로 NKS에 cluster-wide로 설치하자는 PR이 왔습니다. 무엇이 먼저인가요?
섹션 제목: “Q3. Infisical Operator를 바로 NKS에 cluster-wide로 설치하자는 PR이 왔습니다. 무엇이 먼저인가요?”현재 지원 Kubernetes version과 NKS compatibility를 공식 문서·vendor에 확인하고, M7의 Helm release·rollback 기준을 세운 뒤 non-production에서 검증합니다. namespace-scoped RBAC, Machine Identity 권한, native Secret owner, sync 실패 시 기존 값 유지, rotation 후 Deployment reload와 rollback을 확인하기 전에는 production 설치를 승인하지 않습니다.
7. 흔한 함정
섹션 제목: “7. 흔한 함정”함정 1. base64를 암호화로 생각하기
섹션 제목: “함정 1. base64를 암호화로 생각하기”Secret data는 쉽게 decode할 수 있습니다. kubectl get secret -o yaml, shell tracing,
printenv, application log로 값을 노출하지 말고 API read 권한·etcd encryption at rest·audit와
rotation을 별도 제어로 봅니다.
함정 2. source object 변경이 실행 중 env를 바꾼다고 가정하기
섹션 제목: “함정 2. source object 변경이 실행 중 env를 바꾼다고 가정하기”ConfigMap·Secret env는 process 시작 시 snapshot입니다. 변경 뒤 rollout하지 않고 scale만 하면 old/new 값이 섞일 수 있습니다. rollout trigger와 소비자 수렴 검증을 배포 계약에 포함합니다.
함정 3. optional: true로 typo를 숨기기
섹션 제목: “함정 3. optional: true로 typo를 숨기기”필수 key가 없을 때 startup을 막는 편이 잘못된 설정으로 요청을 처리하는 것보다 안전할 수 있습니다. 정말 optional인 feature만 기본값·관측 신호와 함께 optional로 설계합니다.
실제 production Secret 처리, production NKS 변경, control plane·etcd 운영, KMS·NCP IAM 상세, Terraform과 Infisical 설치는 제외합니다. Secret volume·CSI·sidecar/agent injection, immutable ConfigMap·Secret과 automatic reloader는 심화 범위입니다.
8. 다음 모듈 연결 고리
섹션 제목: “8. 다음 모듈 연결 고리”M6에서는 이 Pod template에 label·selector, requests·limits와 toleration을 더해 어떤 node pool에 배치할지와 배치 실패를 판단합니다.