Kubernetes ‐ PV & PVC, Deployment, Service, HPA - thought-corner/Backend-PlayGround GitHub Wiki
PV와 PVC의 핵심 개념 및 인프라 격리
- 쿠버네티스는 클러스터와 네임스페이스를 철저히 분리하는 아키텍처를 지향한다.
- PV(PersistentVolume)
- 정의 : 실제 물리적인 가상/실제 스토리지 리소스(AWS EBS, Azure Disk)를 추상화한 쿠버네티스 오브젝트이다.
- 특징 : Node와 마찬가지로 특정 네임스페이스에 종속되지 않는 클러스터 레벨의 자원이다.
- PVC(PersistentVolumeClaim)
- 정의 : 사용자가 파드에 디스크를 붙이기 위해 쿠버네티스에 제출하는 스토리지 요청서이다.
- 특징 : Pod와 동일하게 특정 네임스페이스 내에 존재한다.
hostPath
hostPath는 파드가 떠 있는 실제 노드(서버 호스트)의 특정 디렉터리를 파드 내부와 바로 연결하는 방식이다.- 왜 지양해야 하는가?
- 파드가 죽었다가 Node2에서 다시 켜지면 Node1에 저장되어 있던 데이터에 접근할 수 없다.
- 즉, 쿠버네티스의 핵심인 '스케줄링 유연성'을 완전히 망가뜨린다.
- 노드 자체의 시스템 로그를 수집해야 하거나 로컬 테스트 환경에서 임시로 쓸 때만 예외적으로 쓴다.
nodeAffinity
local볼륨 유형을 쓰면 물리 디스크를 활용하기 위해 PV에nodeAffinity를 필수로 걸어야 한다.- 이
nodeAffinity는 특정 노드로 파드를 강제 지정하는 속성을 말한다. local볼륨을 쓰면 데이터를 유지할 순 있지만, 결국 파드가 특정 노드에만 종속되므로 쿠버네티스를 쓰는 의미가 퇴색된다.
Deployment
Deployment, ReplicaSet, Pod의 운영 메커니즘
kubectl apply로 Deployment의 이미지 버전(v1 → v2)을 변경하면, 쿠버네티스는 기존 파드를 직접 수정하지 않는다.- Deployment가 새로운 v2 설정을 가진 새로운 ReplicaSet을 하나 더 만든다.
- 배포 전략 설정에 맞춰 기존 ReplicaSet의 파드 개수는 점진적으로 0으로 줄이고 새로운 ReplicaSet의 파드 개수를 늘려나간다.
RollingUpdate 파라미터 조합 1 - maxUnavailable: 100%, maxSurge: 100%
- 배포를 시작하자마자 기존 v1 파드를 전부 내리고 그와 동시에 v2 파드를 원래 개수만큼 한 번에 생성한다.
- 무중단 배포가 아닌 Recreate 전략과 똑같은 다운타임 효과를 창출한다. 다만 배포 속도는 가장 빠르다.
RollingUpdate 파라미터 조합 2 - maxUnavailable: 0%, maxSurge: 100%
- 기존 v1 파드는 단 하나도 죽이지 않은 상태에서 v2 파드를 원래 개수만큼 통째로 먼저 다 띄운다.
- v2 파드가 전부 헬스체크에 성공하면 그 때 트래픽을 넘기고 v1 파드를 한 번에 정리한다.
- 순간적으로 파드 개수가 2배로 뛰기 때문에 클러스터의 CPU/메모리 자원 사용량이 200%로 폭증한다. 인프라 자원이 넉넉할 때만 쓸 수 있다. 그러나 가장 안전한 무중단 배포 방식으로 배포 중에도 서비스 능력이 100% 유지된다.
RollingUpdate 파라미터 조합 3 - maxUnavailable: 25%, maxSurge: 25%
- 예를 들어, 4개의 파드가 있다면 1개를 먼저 죽이고 1개를 먼저 새로 띄우면서 점진적으로 교체한다.
- 자원 여유가 많지 않은 상황에서 클러스터에서 적당한 가용성을 유지하며 배포하는 가장 무난한 설정이다.
Blue/Green 배포
- 쿠버네티스 순정 기능이 아닌 외부 배포 솔루션이나 서비스 매시를 통해 주로 구현하는 고급 전략이다.
- v1 버전(Blue)과 v2 버전(Green)을 클러스터에 동시에 완벽하게 띄워놓고, 앞단에 있는 로드밸런서의 라우팅 스위치만 한순간에 돌리는 방식이다.
- RollingUpdate와의 차이점 : RollingUpdate는 배포 중에 v1, v2 파드가 섞여 있어서 사용자가 요청을 보낼 때 v1으로 갔다가 v2로 갔다가 하는 버전 공존 기간이 생긴다.
- Blue/Green은 공존 기간 없이 단 1초 만에 전원 v2 버전만 바라보게 전환된다.
- 배포 중 두 버전이 섞여 발생하는 데이터나 API 호환성 문제가 없고 문제가 생겼을 때 다시 원복하기가 매우 쉽다. 그러나 자원 사용량이 완벽하게 200% 필요하므로 비용이 많이 든다.
Service
Service Object가 반드시 필요한 이유
- 쿠버네티스에서 파드는 동적으로 생성되고 삭제되는 임시 자원이다. 파드가 재시작될때마다 내부 IP 주소는 매번 변경된다.
- 문제점 : 백엔드 파드가 API 통신을 하거나 프론트엔드가 백엔드를 호출할 때, 자꾸 바뀌는 파드의 고정되지 않은 IP를 직접 바라보게 하는 것은 불가능하다.
- 해결책 : 파드 앞단에 고정된 가상 IP와 도메인을 가진 Service를 두고 서비스가 변경되는 파드의 IP를 실시간으로 추적 및 로드밸런싱한다.
Service Registry와 Service Discovery
- Service Registry란, 조건에 맞는 파드들의 IP 목록을 Endpoints라는 리스트로 들고 관리한다.
- 배포 발생 시 동작
- Recreate나 RollingUpdate에 의해 기존 v1 파드가 삭제되면 Service Registry에서 해당 파드 IP가 즉시 제거된다.
- 새로운 v2 파드가 생성되어 Ready 상태가 되면, 서비스 레지스트리에 새로운 파드의 IP가 자동 등록된다.
- 외부에서 들어오는 유저 트래픽은 실시간으로 업데이트되는 레지스트리 내의 정상적인 파드 IP들로만 로드밸런싱되어 전달되므로, 사용자는 끊김 없는 통신을 보장받는다.
3대 포트 매핑 구조
port: 클러스터 내부에서 파드들이 이 서비스를 호출할 때 사용하는 포트이다.targetPort: 서비스가 트래픽을 최종적으로 전달할 파드 내부의 실제 애플리케이션 포트이다.nodePort: 클러스터 외부 사용자가 물리적인 노드의 IP를 통해 직접 서비스에 접속할 수 있도록 열어주는 포트이다. 쿠버네티스 내부 규칙에 의해 보통 30000~32767 사이의 포트가 할당된다.
네임스페이스 기반 서비스 디스커버리
- 동일 네임스페이스 내부 통신 : 동일 네임스페이스 내부의 파드들끼리는 서비스 이름만으로도 즉시 통신이 가능하다.
- 서로 다른 네임스페이스 간 통신 : 서로 다른 네임스페이스의 파드를 호출하려면
http://api-tester-1231.anotherclass-123:80과 같이[서비스 이름].[네임스페이스 이름]규격을 확장하여 도메인을 명시해야 정상적으로 찾아갈 수 있다.
apiVersion: v1
kind: Service
metadata:
name: api-tester-1231
namespace: anotherclass-123
spec:
type: NodePort # 외부 퍼블리싱을 위해 NodePort 타입 선택 (기본값은 ClusterIP)
# [1] Selector: 어떤 파드들을 이 서비스에 묶을지 라벨 지정 (그림의 selector 필수값 구조)
selector:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-1231-files
# [2] 포트 매핑 삼총사 설정
ports:
- name: http
protocol: TCP
port: 80 # 클러스터 내부 파드들이 접근하는 서비스 포트
targetPort: 8080 # 파드 내부 컨테이너(Spring Boot JAR)에서 돌아가는 포트
nodePort: 31231 # 외부 사용자가 노드 IP를 통해 접속하는 포트
HPA(Auto Scaling)
HPA 정의와 연계 구조
- HPA(Horizontal Pod Autoscaler)는 CPU, 메모리 등의 메트릭을 모니터링하다가 설정한 임계치를 넘어가면 Deployment의 replicas 값을 자동으로 수정하여 파드의 개수를 늘리거나 줄이는 오브젝트이다.
scaleTargetRef: HPA가 감시하고 제어할 대상을 지정한다.minReplicas,maxReplicas: 아무리 부하가 낮아도 최소 최소 2개는 유지하고 아무리 부하가 높아도 최대 4개까지만 늘리겠다는 마지노선을 정의하여 인프라 비용 폭증을 방지한다.
apiVersion: autoscaling/v2
kind: HPA
metadata:
name: api-tester-1231-default
namespace: my-team
spec:
# [1] 스케일링 대상 지정 (그림의 scaleTargetRef)
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-tester-1231
minReplicas: 2 # 최소 파드 수
maxReplicas: 4 # 최대 파드 수
# [2] 확장 기준 메트릭 정의 (CPU 사용량이 Request 대비 60%를 넘을 때)
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
# [3] 급격한 확장/축소 제어 튜닝 (그림의 behavior)
behavior:
scaleUp:
stabilizationWindowSeconds: 120 # 부하 지속성을 확인하는 안전장치 (2분)
policies:
- type: Percent
value: 100
periodSeconds: 15
scaleDown:
stabilizationWindowSeconds: 600 # 트래픽 감소 시 섣부른 축소를 막는 안전장치 (10분)
policies:
- type: Percent
value: 10
periodSeconds: 60