티스토리 뷰
[인프런 복습] 쿠버네티스 어나더클래스(7) - Application 기능으로 이해하기#3 - PV/PVC, Deployment, Service, HPA
터프남 2025. 4. 13. 14:52✅ 아래 글의 내용 및 이미지는 인프런 "쿠버네티스 어나더 클래스 (지상편) - Sprint 1, 2" 강의를 듣고 정리한 글입니다.
쿠버네티스(Kubernetes)를 사용해 애플리케이션을 배포하다 보면, 데이터의 영구 저장은 피할 수 없는 과제입니다. 컨테이너는 기본적으로 상태를 유지하지 않으므로, 데이터베이스나 파일 저장소처럼 지속적으로 데이터를 보존해야 하는 경우 특별한 설정이 필요합니다. 이때 등장하는 것이 바로 PVC(Persistent Volume Claim)와 PV(Persistent Volume)입니다.

PVC와 PV의 기본 개념
PVC(Persistent Volume Claim)란?
PVC는 애플리케이션이 필요로 하는 저장소의 요구사항을 정의하는 쿠버네티스 리소스입니다. 쉽게 말해, "내 애플리케이션에 특정 크기와 접근 모드를 가진 저장소가 필요해!"라고 요청하는 방식입니다. 예를 들어
- 2GiB의 저장소가 필요하고, 여러 노드에서 읽기/쓰기(ReadWriteMany)가 가능해야 한다.
- PVC는 Pod가 직접 저장소에 접근할 수 있도록 중간 다리 역할을 합니다.
PV(Persistent Volume)란?
PV는 클러스터 내에서 실제로 사용할 수 있는 저장소를 나타냅니다. 이는 물리적인 디스크나 네트워크 스토리지(NFS, AWS EBS 등)와 연결되며, 쿠버네티스 클러스터에서 관리됩니다. PV는 PVC의 요청에 맞춰 저장소를 제공하며, 예를 들어
- 2GiB의 저장소를 제공하며, 로컬 디렉토리(/root/k8s-local-volume/1231)에 연결된다.
PVC와 PV의 관계
- PVC는 PV에 대한 요청을 보내고, PV는 그 요청에 부합하는 저장소를 제공합니다.
- PVC와 PV는 1:1로 바인딩되며, Pod는 PVC를 통해 영구 저장소에 접근합니다.
- 이를 통해 애플리케이션은 클러스터 내에서 데이터 영구성을 보장받을 수 있습니다.
왜 PVC와 PV가 꼭 필요한가요?
- 쿠버네티스 개념적으로 파드를 만드는 주체는 개발자이다.
- 볼륨 솔루션들에는 여러가지가 있고 각각의 기능에 따라서 써야되는 속성도 달라지기 때문에 개발자가 파드를 만들면서 이런것 까지 신경쓰는 건 좀 아니라는 생각을함.
- 그래서 인프라 담당자가 이걸 관리하는 컨셉으로 PV라는 오브젝트를 만드는것
- PVC는 파드에서 필요한 자원을 요청하는 정도로 개발자가 만드는데 이렇게 인터페이스 역할을 해주는게 있어야지 PV의 솔루션이 변경되더라도 파드까지 손을 대는 일은 없어지게 된다.
- 그래서 PVC와 PV라는 오브젝트가 있다고 생각하면 된다.
- 아직 와닿지 않아도 계속 공부해보자.
Deployment (Recrate, RollingUpdate, MaxUnavailable, maxSurge)

앱에 새로운 버전이 나와서 업데이트를 해야 될 때 기존 파드는 삭제하고 새 파드를 배포해야 하는데 k8s는 deployment라는 오브젝트에서 strategy라는 속성으로 기능을 지원해준다.
template 밑에 있는 내용이 하나라도 변경이 되면 업데이트가 진행된다.
Recreate
- 파드가 두 개 있는 상태에서 k8s는 바로 기존 파드를 모두 삭제시키는 동시에 새 파드 두 개를 만든다.
- 이 파드들은 처리되는 속도에 따라서 기동되는 시간이 차이가 있을 수 있다.
- 첫 번째 파드가 기동되는 시간만큼 서비스 중단이 업데이트 과정에서 생긴다는 특징이 있다.
RollingUpdate
- 먼저 새 버전의 파드를 만들기 시작 후 기동이 완료되자마자 기존 파드를 하나 삭제한다.
- 반복적으로 새 파드를 또 만들고 또 기동이 완료되자마자 기존 파드를 삭제 시킨다.
- 특징으로는 업데이트 중에 서비스 중단이 없다.
- 서비스 중단이 있어도 되면 Recreate를 쓰면 된다. 그러나 중단이 없어야 한다면 롤링업데이트를 쓰는게 맞다.
- 업데이트 중에는 자원 사용량이 150% 증가한다.
- 업데이트 중에는 두 버전이 동시에 호출된다는 문제도 있다.
- 이럴 때는 블루/그린 이라는 배포 방식도 있다. 업데이트 동안 두 버전이 동시에 호출되지는 않지만 자원 사용량이 200%가 된다.
- 블루/그린 배포는 별도 배포 솔루션을 설치해야지 쓸 수 있는 기능이다.
maxUnavailable이란?
- 정의: maxUnavailable은 업데이트 중에 사용할 수 없는(unavailable) 파드의 최대 개수를 지정합니다. 즉, 최소한 유지해야 하는 가용 파드 수를 보장합니다.
- 쉽게 설명: "업데이트 중에도 최소한 몇 개의 파드는 반드시 실행 중이어야 한다"는 규칙입니다. 예를 들어, 10개의 파드가 있고 maxUnavailable이 2라면, 업데이트 중에 최대 2개의 파드가 내려가도 괜찮다는 뜻입니다. 즉, 최소 8개의 파드는 항상 가용해야 합니다.
- 계산 방식:
- 전체 파드 수에서 maxUnavailable을 뺀 값이 최소 가용 파드 수입니다.
- maxUnavailable은 절대값(예: 2) 또는 백분율(예: 20%)로 설정할 수 있습니다.
- 예시:
- 파드 10개, maxUnavailable: 20% → 최대 2개 파드가 내려갈 수 있으므로 최소 8개 파드가 가용해야 함.
maxSurge란?
- 정의: maxSurge는 업데이트 중에 추가로 생성할 수 있는 파드의 최대 개수를 지정합니다. 즉, 원래 파드 수보다 더 많은 파드가 일시적으로 존재할 수 있는 한도를 설정합니다.
- 쉽게 설명: "업데이트 중에 새 파드를 추가로 몇 개까지 더 띄울 수 있느냐"를 결정합니다. 예를 들어, 10개의 파드가 있고 maxSurge가 2라면, 업데이트 중에 최대 12개 파드(10 + 2)가 동시에 존재할 수 있습니다.
- 계산 방식:
- 원래 파드 수에 maxSurge를 더한 값이 최대 파드 수입니다.
- maxSurge도 절대값(예: 2) 또는 백분율(예: 20%)로 설정 가능합니다.
- 예시:
- 파드 10개, maxSurge: 20% → 최대 2개 파드를 추가로 생성할 수 있으므로, 최대 12개 파드가 동시에 실행될 수 있음.
Service

- 오브젝트를 보면 selector와 label로 Service가 파드를 연결한다.
- type이 있는데 지금까지는 nodePort 타입으로 설정을 해서 썼다.
- 노드가 있고 포트가 만들어지면서 외부에서 보낸 트래픽을 쿠버네티스 내부의 파드로 전달할 수가 있다.
- targetPort는 컨테이터 port를 가리키는 것이다.
- 그림에서 보이는 것처럼 http://192.168.56.30:31231/version 으로 외부 요청을 하면 파드의 앱 까지 전달이된다.
- 이렇게 서비스 역할 중에 하나가 서비스 퍼블리싱이다.
- 서비스에 type을 넣지 않으면 default가 ClusterIP 이다.
- ClusterIP type은 오직 k8s 내부에 Pod에서만 접근하는 용도이다.
- 서비스의 두번째 역할로 Service Discovery라고 해서 k8s가 내부 DNS를 이용해서 서비스의 이름을 API로 호출을 할 수 있게 해주는 기능이 있다.
- 그래서 서비스 이름과 80 포트를 넣어서 API를 호출하면 내부적으로 target port로 포워딩이 돼서 트래픽이 POD로 전달이 된다.
- ex) http://api-tester-1231:80/version
- 파드와 서비스에는 생성이 될때 부여되는 아이피가 있다.
- 파드의 경우는 삭제 될 때 아이피가 변경되기 때문에 항상 서비스를 통해서 호출해야 한다.
- 서비스는 한번 만들어놓으면 삭제할 일이 없지만 아이피를 기억하기 힘들기 때문에 DNS를 쓰고 k8s도 서비스 이름을 자동으로 내부 DNS에 등록해주기 때문에 도메인 명으로 쉽게 원하는 파드의 API를 요청할 수 있다.
- 클러스터의 다른 네임스페이스에 있는 파드가 호출을 할 때는 서비스 이름 뒤에 해당 pod가 속해있는 namespace 이름까지 넣어줘야 한다.
- http://api-tester-1231.anotherclass-123:80/version
Pod의 컨테이너의 포트가 변경된다면?
- Pod의 컨테이너가 포트가 바뀌더라도 서비스까지는 신경쓰지 않게 하는 방법이 있다.
- pod에도 containerPort라는 속성을 줄 수가 있다.
- pod에 컨테이너 포트 속성을 주어야지 pod로 api를 호출할 수 있다고 생각할 수 있지만 그것은 아니고 containerPort는 정보성인 속성이라고 보면 된다.
- targetPort에 http를 넣을 수도 있고 이렇게 넣으면 서비스를 호출했을 때 pod에서 이름이 맵핑된 포트를 찾아서 그 포트로 api를 호출한다.
- 그래서 이렇게 name을 쓰면 컨테이너에 포트가 변경되어도 pod만 수정하면 되고 서비스까지 건들 필요가 없어진다.
Deployment에서 업데이트 과정 속 파드 삭제될때 IP
- 업데이트 과정 속에서 파드가 삭제되고 새로 만들어질 때 쿠버네티스가 서비스에 호출되는 IP를 제거하고 등록해주고 있기 때문에 파드에 서비스만 연결해 놓으면 파드가 죽어도 호출하는데 신경 쓸게 없게 된다.
- 이런게 서비스 레지스트리 기능이다.
HPA

- 이상적인 스케일링과 현실적인 스케일링을 봤는데 실제 서비스 상황이라고 생각하니 무서웠다.
- 미리 예상하지 못한 트래픽에는 장사 없음..
- 자동화 스케일링은 보조적인 역할로 생각.
- 서비스마다 피크 시간이 언제인지 분석을해서 미리 자원을 늘려놓거나 대기열 아키텍처를 구성하는게 가장 확실하다.
실습
https://cafe.naver.com/kubeops/49
Application 기능으로 이해하기 - PVC/PV, Deployment, Service, HPA
1. PV, PVC - search 1-1. local, hostPath 1-2. 동작 확인 ▶ 1~4. local 동작 확인 ▶ 5. hostPath 동작 확인 - Depl...
cafe.naver.com
출처
쿠버네티스 어나더 클래스 (지상편) - Sprint 1, 2 강의 | 일프로 - 인프런
일프로 | , ✅ 광범위한 쿠버네티스 기술을 A~Z까지 넓고 얇게 훑기보다 하나의 개념을 배우더라도 왜 사용하는지 부터 실무에서 어떻게 사용되는지 까지를 다루는 강의 ✅ 시작은 초급자지만
www.inflearn.com
- Total
- Today
- Yesterday
- window
- elasticsearch
- claude
- oracle
- localtime
- maven
- input
- Spring Security
- springboot
- Mac
- LocalDate
- Java
- LocalDateTime
- JavaScript
- 오라클
- jQuery
- Spring
- rocky
- 북리뷰
- mybatis config
- mybatis
- intellij
- docker
- config-location
- 베리 심플
- Linux
- Kotlin
- svn
- Bash tab
- k8s
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |