본문으로 바로가기
6. 설정과 저장소, 앱을 운영할 수 있는 상태로 만들기
LinkedInGitHub
WORKSPACE

EXPLORER

157 POSTS
BLOG
면접질문
해야하는 거
AI 시대, 개발자는 사라지는가?
Python Counter, 빈도수를 쉽게 세는 방법
정렬
1. 투 포인터
DFS와 BFS
알고리즘 논리
코딩 테스트 핵심 알고리즘 정리파이썬 딕셔너리와 코딩 테스트 활용
예시로 살펴보는 AXAX 프로젝트, 문제 정의부터 확산까지AX 시대의 가치 정의와 현장 리딩
MSA
1. Singleton PatternSOLID
Kafka의 핵심 설계 원리Kafka 메시징 시스템의 구성과 동작 방식Kafka 기본 개념과 EC2 Docker 구성
쿠버네티스 입문
Modular Monolith1. MonolithMSA, 서비스 분리와 운영의 원리
Socket이란 무엇인가
네크워크 참조 모델
전체 데이터 구조REST API의 개념과 설계 원칙2. Field/ Parameter / Argument/ this
Actuator 란?EntityManagerJPA 연관관계 매핑JPA 트랜잭션(Transaction)입력값 검증Java의 AOP(Aspect Oriented Programming)Async : AsynchronousBeanJPA(Java Persistence API)Proxy 패턴Spring MVCdocker container1. Spirng 필요컴포넌트 스캔
Spring 컨테이너
application.yamlLombok
이번 강의는 무엇을 노리고 있을까?Spring AI를 배우기 전에 정리할 것23
1. 기술 스택
개발 문서를 읽기 위한 핵심 기술 용어
Docker를 이해하기 위한 운영체제 기초
sigterm
6. 설정과 저장소, 앱을 운영할 수 있는 상태로 만들기5. Service와 Ingress, 요청은 어디로 흐를까4. 직접 실험하는 Kubernetes, Pod 복구부터 롤백까지3. kubectl과 Pod, 상태에서 원인을 찾는 법2. 클러스터는 명령을 어떻게 Pod로 바꿀까1. 쿠버네티스, 원하는 상태와 컨테이너 이미지Calico쿠버네티스 입문, 원하는 상태를 유지하는 시스템
Psql JSONB, 행 잠금, 멱등성Psql 함수,프로시져,트리거
머신러닝 입문딥러닝 학습 기본 개념데이터 시각화기초 통계와 ML 파이프라인 연결분석 자동화와 파이프라인 설계
CNN 아키텍처 발전 과정이미지 세그멘테이션 모델과 핵심 개념객체 탐지 모델과 핵심 개념
딥러닝 데이터셋 엔지니어링
딥러닝 학습 문제 진단과 디버깅
도메인 적응 방법현대 LLM 워크플로의 패턴
Transformer에서 LoRA 적용 대상 정하기LoRA (Low-Rank Adaptation)
LLM 양자화와 QLoRA
분산 학습과 MLOps딥러닝 모델 경량화와 추론 최적화딥러닝 기본 학습 테크닉딥러닝 중급 학습 테크닉
Mixture of Experts(MoE) 핵심 개념멀티모달 파운데이션 모델 핵심 개념State Space Model과 MambaTransformer와 Vision Transformer
Latent Space
1Chunking?
DevOps 기초 1편
실습에서는?Agile 개요, 왜 필요한가?
CI/CD 기초 4편: 배포 전략과 운영CI/CD 기초 3편: Jenkins와 Argo CD를 이용한 GitOps 배포CI/CD 기초 2편: Docker 이미지와 배포 파이프라인CI/CD 기초 1편: 개념과 GitHub Actions
OCI: 컨테이너 이미지와 런타임의 공통 표준Docker 기초 13편: Compose Healthcheck와 실전 구성Docker 기초 12편: Compose 네트워크와 VolumeDocker 기초 11편: Compose 명령어와 환경 변수Docker 기초 10편: Compose 기본 구조와 이미지 빌드Docker 기초 9편: Docker 및 Kubernetes 네트워크Docker 기초 8편: 컨테이너 런타임과 격리Docker 기초 7편: 이미지 Layer와 tar 내부 구조Docker 기초 6편: 이미지 Layer와 빌드 최적화Docker 기초 5편: 컨테이너 기본 명령어와 VolumeDocker 기초 4편: 가상화와 컨테이너 이미지 생명주기Docker 기초 3편: CI/CD 연결과 배포 원칙Docker 기초 2편: Layer, Registry, Volume과 NetworkDocker 기초 1편: Dockerfile, Image와 Container
NginxNginx 로드 밸런싱과 HTTPSNginx 리버스 프록시와 Spring Boot 연결Nginx 기초와 동작 구조
05. Pinia 상태 관리: store 설계와 사용법04. Vue 컴포넌트 설계: props, emit, slot과 생명주기03. Vue Composition API 정리02. Vue 기초 문법 점검: JavaScript, 템플릿01. Vue.js 입문: 핵심 구조와 렌더링
Java 심화 Part 3: 함수형 프로그래밍과 LambdaJava 심화 Part 2: AnnotationJava 심화 Part 1: Reflection
Java 기초 Part 5: Stream APIJava 기초 Part 4: 제네릭Java 기초 Part 3: 제어문Java 기초 Part 2: 주석과 JavadocJava 기초 Part 1: 백엔드 배경과 Java 실행 구조
Java 디버깅 Part 1: 자주 헷갈리는 핵심 개념Java 디버깅 Part 2: VS Code 자동 컴파일과 프로젝트 구조
Java 실행과 JVM Part 3: ClassLoader와 JVM 메모리Java 실행과 JVM Part 2: 메모리와 데이터 흐름Java 실행과 JVM Part 1: Java와 Python 컴파일 비교
Java 객체지향 Part 5: static 메서드와 중첩 클래스Java 객체지향 Part 4: 상속과 인터페이스Java 객체지향 Part 3: 좋은 설계와 OOP 4대 특성Java 객체지향 Part 2: OOP 핵심 문법Java 객체지향 Part 1: 클래스, 객체, 필드와 생성자
Spring 기초 Part 11: Actuator와 애플리케이션 모니터링Spring 기초 Part 10: 비동기 처리와 @AsyncSpring 기초 Part 9: JPA 트랜잭션과 동시성 제어Spring 기초 Part 8: AOP와 공통 관심사 분리Spring 기초 Part 7: Proxy 패턴과 Spring ProxySpring 기초 Part 6: JPA 연관관계 매핑Spring 기초 Part 5: EntityManager와 영속성 컨텍스트Spring 기초 Part 4: JPA, Entity와 RepositorySpring 기초 Part 3: REST API 요청값과 입력값 검증Spring 기초 Part 2: Spring MVC 요청 처리 흐름Spring 기초 Part 1: IoC, Bean, DI와 주요 Annotation
DNS = Domain Name System
Spring Boot, WebSocket, Vue, Docker 로 Raspberry Pi 실시간 모니터링 프로젝트 만들기 - 1편1. Spring Boot 구현
1. GitHub Project 만들기
Python 코드 품질: 디버깅부터 테스트와 자동화까지Python 01. 실행 구조와 실무 기초
sLLM 핵심 기술과 전체 구조제한된 자원에서 sLLM 구축하기
시대 단상에 대한 주저리주저리
WORKSPACE

SEARCH

제목, 카테고리와 태그로 검색하세요.

VERSION CONTROL

SOURCE CONTROL

masterGitHub Pages
저장소 열기
BUILD STATUS

RUN AND DEBUG

게시물은 GitHub Actions에서 검증하고 정적 페이지로 빌드합니다.

Actions 열기
WORKSPACE

MANAGE

홈 열기전체 게시물태그 보기블로그 소개
6. 설정과 저장소, 앱을 운영할 수 있는 상태로 만들기●
workspace>posts>ci-cd-docker>kubernetes>part-6.md
CI-CD-Docker / kubernetes2026.09.071 min read6 tags

6. 설정과 저장소, 앱을 운영할 수 있는 상태로 만들기

ConfigMap과 Secret의 반영 시점, 볼륨의 수명, requests와 limits, 프로브와 종료 처리를 하나의 배포 조건으로 연결한다.

QUICK SUMMARY

핵심 요약

운영 준비는 같은 이미지를 환경별 설정으로 실행하고, 필요한 데이터를 Pod 수명 밖에 보존하며, 자원과 종료 조건을 맞추는 일이다. 설정 객체가 바뀌는 시점과 앱이 새 값을 쓰는 시점은 다르다. 배포 성공은 실제 준비 상태와 요청 결과로 확인한다.

KEY CONCEPTS

핵심 개념

  • ConfigMap / Secret: 일반 설정 / 민감한 값의 분리
  • PVC / PV / StorageClass: 저장소 요청 / 볼륨 객체 / 제공 방식
  • requests / limits: 배치를 위한 자원 요청 / 실행 자원 제한
  • Graceful shutdown: 처리 중 요청을 정리한 뒤 종료

실행된다는 것과 운영할 수 있다는 것은 다르다

운영 가능한 앱은 재시작과 교체를 견디도록 설정, 데이터, 자원과 종료 동작을 준비해야 한다. Pod가 한 번 Running이 된 것만으로 이 조건이 검증되지는 않는다.

4편 실험실은 Pod가 교체되어도 서비스가 이어지는 구조를 보여준다. 이 파트는 그 구조 바깥에서 앱이 지켜야 하는 조건을 정리한다. ConfigMap, Secret, 볼륨과 자원 제한은 본문의 학습 범위이며 모형이 실행하는 기능은 아니다.

1. 같은 이미지를 환경별 설정으로 실행한다

개발, 검증, 운영마다 이미지를 새로 만드는 것보다 검증한 이미지에 환경별 설정을 주입하면 무엇을 배포했는지 추적하기 쉽다. 앱 코드와 환경에 따라 달라지는 값을 분리하는 이유다.

ConfigMap은 일반 설정을 키와 값 또는 파일 형태로 담는다. Secret은 민감한 값을 별도 객체로 다룬다. ConfigMap의 값은 문자열이므로 숫자처럼 보이는 값도 문자열로 의도했다면 따옴표를 붙여 표현한다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: shop-config
data:
  APP_MODE: "demo"
  ORDER_TIMEOUT_MS: "3000"

Secret의 base64 표현은 암호화가 아니다. 읽을 권한이 있는 사람은 원래 값을 복원할 수 있다. 저장 시 암호화와 접근 권한 등 실제 보호 설정은 클러스터 구성에 따라 별도로 확인한다. 이름이 Secret이라는 이유만으로 Git에 올려도 안전한 값이 되는 것은 아니다.

2. 설정 객체 변경과 앱 반영은 다른 사건이다

ConfigMap을 수정했다고 이미 실행 중인 프로세스의 환경변수가 자동으로 바뀌지는 않는다. 값을 어디에 주입했고 앱이 언제 읽는지까지 봐야 한다.

주입 방식값이 전달되는 시점변경 뒤 필요한 확인
환경변수컨테이너 시작 시새 컨테이너가 새 값을 받았는가
일반적인 ConfigMap 볼륨파일로 마운트, 변경은 지연 후 반영 가능파일 갱신과 앱의 재읽기가 모두 이루어졌는가
subPath 파일 마운트특정 경로를 마운트일반 볼륨처럼 자동 갱신되지 않는 제약 확인
앱의 외부 설정 조회앱의 구현과 조회 정책에 따름캐시와 갱신, 실패 처리

파일만 새로 바뀌고 앱이 시작할 때 한 번 읽은 값을 계속 사용한다면 동작은 그대로다. 반대로 환경변수를 갱신하려고 롤아웃을 했다면 새 Pod가 설정을 읽고 준비됐는지까지 확인한다.

Deployment는 Pod template이 바뀔 때 새 롤아웃을 만든다. 별도 ConfigMap의 내용만 바꾸는 것은 Pod template 변경과 다르다. 설정 버전이나 해시를 template에 반영하는 방식은 이 둘을 연결하려는 방법이다.

3. 데이터는 필요한 수명에 맞는 곳에 둔다

남겨야 하는 데이터의 수명이 컨테이너나 Pod보다 길다면 저장소를 분리해야 한다. 단순히 볼륨이 있다는 사실보다 어떤 삭제와 재시작을 견디는지가 중요하다.

위치일반적인 수명 기준사용할 데이터의 성격
컨테이너의 쓰기 영역해당 컨테이너 실행사라져도 다시 만들 수 있는 임시 파일
emptyDirPod 수명같은 Pod의 컨테이너가 공유하는 임시 작업
PVC로 연결한 저장소볼륨과 반환 정책에 따름Pod가 교체되어도 보존할 파일
외부 DB, 객체 저장소해당 외부 서비스의 정책앱 복제본과 독립적으로 관리할 상태

컨테이너만 재시작되면 emptyDir는 남아 있지만 Pod가 삭제되면 사라진다. PVC를 사용하더라도 삭제 정책에 따라 실제 저장소가 제거될 수 있다. 영속 저장소를 사용했다는 사실이 백업을 대신하지는 않는다.

로그를 stdout과 stderr로 출력하는 것과 로그가 장기 보존되는 것도 별개다. 별도의 수집과 저장 구성이 있어야 Pod가 사라진 뒤에도 조사할 근거가 남는다.

4. PVC는 요청, PV는 볼륨을 나타내는 객체다

애플리케이션은 필요한 저장 공간을 PVC로 요청하고, 실제 저장소 제공 방식은 StorageClass와 프로비저너가 맡을 수 있다. 앱이 모든 디스크 생성 절차를 직접 알 필요를 줄인다.

Pod의 volume 참조
  → PVC: 필요한 용량과 접근 모드
  → StorageClass와 프로비저너: 제공 방식
  → PV: 연결된 볼륨을 나타내는 객체
  → 실제 저장소와 마운트

WaitForFirstConsumer 방식은 사용할 Pod의 배치 조건을 고려할 때까지 볼륨 바인딩이나 생성을 지연한다. 따라서 PVC가 Pending이라는 사실만으로 오류라고 단정하지 않는다. 반대로 계속 진행되지 않는다면 Events, StorageClass, 드라이버와 배치 조건을 확인한다.

접근 모드는 특히 정확히 구분해야 한다. ReadWriteOnce는 한 Pod만이 아니라 한 Node에서 읽고 쓸 수 있다는 의미다. 같은 노드의 여러 Pod가 접근할 가능성과 저장소 자체의 제약을 함께 봐야 한다. 한 Pod로 제한하는 의미는 ReadWriteOncePod와 구분한다. 공식 Persistent Volumes 문서

RWO 저장소를 쓰는 Pod가 서로 다른 Node로 배치되면 멀티 어태치 같은 문제가 생길 수 있다. 공유 파일, 개별 복제본의 데이터, 객체 저장소 중 무엇이 앱의 일관성 요구에 맞는지 먼저 정해야 한다.

5. requests는 배치의 기준이고 limits는 실행의 제한이다

Scheduler가 자리를 계산하는 값과 실행 중 자원 사용을 제한하는 값은 용도가 다르다. 둘을 같은 “최대 사용량”으로 읽으면 배치와 장애를 혼동한다.

# containers의 app 항목 아래에 들어가는 설정 조각
resources:
  requests:
    cpu: "250m"
    memory: "512Mi"
  limits:
    cpu: "1"
    memory: "1Gi"

CPU의 1000m은 CPU 한 단위에 해당한다. Mi, Gi는 1024 기반이고 M, G는 1000 기반이다. 같은 숫자라도 단위에 따라 다른 양이 된다.

CPU 제한은 사용 시간을 제한해 지연을 만들 수 있고, 메모리 제한에 도달하면 OOM 종료가 발생할 수 있다. 값은 앱의 기동 구간과 부하 변화, JVM 힙 밖 메모리까지 관찰해 정한다. 예제에 쓰인 수치를 모든 앱의 적정값으로 사용하지 않는다.

QoS는 자원 설정으로부터 결정된다. BestEffort, Burstable, Guaranteed 구분은 노드 압박 상황을 이해하는 단서지만, 실제 축출 판단은 우선순위와 요청 대비 사용량 등도 함께 고려하므로 QoS 이름 하나로 순서가 항상 고정된다고 보지는 않는다.

6. 종료도 정상 요청 처리의 일부다

새 Pod가 Ready가 되는 과정만큼, 기존 Pod가 처리 중 요청을 끝내고 종료하는 과정도 중요하다. 롤링 업데이트 설정 하나로 모든 요청의 무중단을 보장할 수는 없다.

삭제 요청
  ├── 연결 대상의 준비/종료 조건 갱신
  └── kubelet 종료 처리
        → preStop이 있으면 실행
        → SIGTERM 전달
        → 앱이 진행 중 작업을 정리
        → 유예 시간이 끝나면 강제 종료 가능

preStop에 쓴 시간도 종료 유예 예산 안에 들어간다. 예를 들어 훅에 5초, 앱 종료 작업에 최대 25초가 필요하다고 가정하면 유예를 20초로 두어서는 정리를 마칠 수 없다. 실제 종료 시간을 측정해 여유를 정해야 한다.

고정된 sleep 5초를 넣었다는 사실만으로 전파 지연이나 모든 긴 요청이 해결되는 것은 아니다. 요청 시간, keep-alive, 연결 해제, 프록시와 앱의 종료 동작을 함께 검증한다. 관리 포트의 헬스체크가 성공해도 서비스 포트가 정상인지 별도 확인이 필요할 수 있다.

7. 배포 성공은 단계별 결과로 확인한다

명령 성공, Pod 준비, 실제 사용자 응답을 서로 다른 증거로 기록해야 한다. 그래야 “배포됐다”는 말이 무엇을 확인한 것인지 분명해진다.

확인 수준확인한 것아직 남은 것
매니페스트 검증필드와 일부 정책이 유효함이미지 실행과 앱 동작
변경 요청 성공API가 선언을 받아들임조정과 컨테이너 준비
롤아웃 완료새 template의 복제본이 준비됨외부 연결과 업무 기능
실제 엔드포인트 호출해당 경로의 응답 확인부하와 장애, 장시간 상태
배포 중 요청 관찰교체 구간의 오류와 지연 확인다른 장애 상황과 복구 절차

문제가 생기면 영향 범위, 최근 변경, 복구 가능한 버전과 외부 데이터 호환성을 먼저 파악한다. 이전 앱으로 돌렸는데 DB 스키마가 맞지 않으면 다른 장애가 생길 수 있다. 복구와 함께 Events, 로그, 지표를 남기고 다음 실험과 재발 방지에 연결한다.

다시 실험할 지점

다시 실험실로 돌아가면, Ready 수와 Endpoints 수가 운영 조건의 일부라는 점이 더 잘 보일 것이다. 4편 실험실에서 실패 배포와 롤백을 다시 관찰하거나, 전체 목차에서 필요한 파트를 골라 읽으면 된다.

TAGS#Kubernetes#ConfigMap#Secret#PVC#리소스#운영
PREVIOUS5. Service와 Ingress, 요청은 어디로 흐를까
DISCUSSION

COMMENTS

GitHub 계정으로 로그인하여 댓글을 남길 수 있습니다. 댓글은 GitHub Discussions에 공개 저장되며, 작성 내용과 GitHub 프로필 정보가 다른 방문자에게 보일 수 있습니다.

GitHub 로그인 후 댓글 쓰기Discussion 열기
DOCUMENT STRUCTURE

이 문서에는 목차가 없습니다.

DOCUMENT INFO
TYPE
Markdown
DATE
2026.09.07
READ
1 min read
WORDS
0
CATEGORY
CI-CD-Docker / kubernetes
RELATED DOCUMENTS
5. Service와 Ingress, 요청은 어디로 흐를까4. 직접 실험하는 Kubernetes, Pod 복구부터 롤백까지3. kubectl과 Pod, 상태에서 원인을 찾는 법2. 클러스터는 명령을 어떻게 Pod로 바꿀까1. 쿠버네티스, 원하는 상태와 컨테이너 이미지쿠버네티스 입문, 원하는 상태를 유지하는 시스템
main CI-CD-Docker / kubernetes
1 min readUTF-8Markdown
본문 글씨 크기
RECENTLY OPENED1
6. 설정과 저장소, 앱을 운영할 수 있는 상태로 만들기recently opened