서론
해당 글은 일프로 님의 인프런 강의 쿠버네티스 어나더 클래스 (지상편) - Sprint 1, 2의 내용을 정리한 글입니다.
해당 글에 사용된 내용, 사진 및 그림은 모두 강의와 강의 자료에 포함된 내용입니다.
PV/PVC (local, hostPath)
- 용도
- 파드가 여러 이유로 인해 종료될 경우에 대비해 보존해야 할 데이터를 관리하기 위함
- PV/PVC를 활용해 파드가 죽어 컨테이너가 종료된다고 하더라도, 쿠버네티스가 재생성한 파드를 다시 PV/PVC와 연결해 데이터 조회 가능
- 의미
- 파드와 볼륨의 결합도를 낮추기 위함
- 파드는 개발자가 관리하며, PV는 인프라 담당자가 관리하기 때문
- 파드-PV 중간에 PVC가 있는 이유는 PV 관련 다양한 솔루션에 종속되지 않도록 인터페이스 역할을 수행하기 위함
![](https://velog.velcdn.com/images/appti/post/37076db3-d2c0-4a39-99ea-a020b4fe60a0/image.png)
local, hostPath
- local
- PV(Persistent Volume)이 노드에 마운트된 로컬 스토리지 디바이스
- nodeAffinity를 통해 어떤 노드에 파드를 생성(스케줄링)할지 지정
- nodeAffinity 속성이 있는 PV와 연결된 파드는 그림에서 Master Node에 생성
- Master Node의 path와 파드 내의컨테이너 디렉토리를 매핑
- hostPath
- 노드의 파일시스템에 있는 파일이나 디렉터리를 파드에 마운트
- 노드에 있는 정보를 애플리케이션에서 조회하는 용도로 사용
- Promtail이 Loki가 수집하는 로그를 hostPath를 활용해 특정 디렉토리에 저장하기 때문에 모든 파드의 로그를 Loki를 통해 확인 가능
- 사용의 편리함으로 인해 테스트 환경에서 임시 저장 용도로도 사용되기는 함
- 노드 공간이 부족해질 수 있기 때문에 운영환경에서는 사용 금지
- 우회 방법이 있기는 하지만(그림에서는 NAS 서버를 활용) 자동화가 힘들기 때문에 지양할 것
- PV/PVC local 속성과 유사한 기능을 제공하나, 더욱 간단하게 사용 가능
- 쿠버네티스 공식 문서에서 사용하지 않는걸 권장하고 있음
실습
- 실습 순서
- 파일 생성 API 호출
- 생성된 파일 확인
- 파드 삭제
- 기존 생성된 파일 다시 확인
local
http://192.168.56.30:31231/create-file-pod
http://192.168.56.30:31231/create-file-pv
kubectl exec -n anotherclass-123 -it api-tester-1231-75dd57f8cb-x5rdl -- ls /usr/src/myapp/tmp
kubectl exec -n anotherclass-123 -it api-tester-1231-75dd57f8cb-x5rdl -- ls /usr/src/myapp/files/dev
ls /root/k8s-local-volume/1231
kubectl delete -n anotherclass-123 pod api-tester-1231-75dd57f8cb-hg54z
http://192.168.56.30:31231/list-file-pod
http://192.168.56.30:31231/list-file-pv
![](https://velog.velcdn.com/images/appti/post/11c96cbe-dc08-401f-a465-6ac5c238b445/image.png)
![](https://velog.velcdn.com/images/appti/post/f49b5f0e-1ca2-4c3e-b7be-ddde158b8eca/image.png)
![](https://velog.velcdn.com/images/appti/post/128224d9-de78-401e-b378-157acab8d632/image.png)
![](https://velog.velcdn.com/images/appti/post/8a1c7ecd-ddea-4059-bad7-e03c12a7f8c5/image.png)
![](https://velog.velcdn.com/images/appti/post/e51b8ed0-e6dd-49b1-ac45-f78fb8ca3c96/image.png)
![](https://velog.velcdn.com/images/appti/post/ef1663d0-4a19-49ef-ab6d-a9f6daf319dd/image.png)
![](https://velog.velcdn.com/images/appti/post/e0796474-9a85-4a19-95e3-6643694eaddd/image.png)
![](https://velog.velcdn.com/images/appti/post/4196e075-834c-49d7-84bd-939138a5abe9/image.png)
- 임시 저장 파일은 삭제되었고 영구 저장 파일은 파드 삭제 후 재생성 시에도 파드 & 노드 양쪽에서 확인할 수 있음
hostPath
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: anotherclass-123
name: api-tester-1231
spec:
template:
spec:
nodeSelector:
kubernetes.io/hostname: k8s-master
containers:
- name: api-tester-1231
volumeMounts:
- name: files
mountPath: /usr/src/myapp/files/dev
- name: secret-datasource
mountPath: /usr/src/myapp/datasource
volumes:
- name: files
hostPath:
path: /root/k8s-local-volume/1231
- name: secret-datasource
secret:
secretName: api-tester-1231-postgresql
http://192.168.56.30:31231/create-file-pod
http://192.168.56.30:31231/create-file-pv
kubectl exec -n anotherclass-123 -it api-tester-1231-5f488b45b4-wh6dt -- ls /usr/src/myapp/tmp
kubectl exec -n anotherclass-123 -it api-tester-1231-5f488b45b4-wh6dt -- ls /usr/src/myapp/files/dev
ls /root/k8s-local-volume/1231
kubectl delete -n anotherclass-123 pod api-tester-1231-5f488b45b4-85czr
http://192.168.56.30:31231/list-file-pod
http://192.168.56.30:31231/list-file-pv
![](https://velog.velcdn.com/images/appti/post/ad2641da-7cbe-47ad-8239-779b7e72dd47/image.png)
![](https://velog.velcdn.com/images/appti/post/7fbb0614-f452-4f37-ab81-e67f804207c6/image.png)
![](https://velog.velcdn.com/images/appti/post/5abe75e5-71f5-4ab2-af32-de6f1d93e7a3/image.png)
![](https://velog.velcdn.com/images/appti/post/1ae2ebdb-c566-4f17-93a2-fb39876f771e/image.png)
![](https://velog.velcdn.com/images/appti/post/e4d73753-5712-43f8-9b21-ba712d00eb3b/image.png)
![](https://velog.velcdn.com/images/appti/post/ceab7592-21db-458f-b15f-2f974f4d80ca/image.png)
![](https://velog.velcdn.com/images/appti/post/2d1dad6a-516e-4076-8842-92495d21eb47/image.png)
![](https://velog.velcdn.com/images/appti/post/3db422da-53e5-409f-8739-701d3e5913ba/image.png)
- 임시 저장 파일은 삭제되었고 영구 저장 파일은 파드 삭제 후 재생성 시에도 파드 & 노드 양쪽에서 확인할 수 있음
Deployment
![](https://velog.velcdn.com/images/appti/post/ffa73b9c-f168-47e7-a256-f8d271e130e3/image.png)
strategy
- strategy
- 파드 업데이트 시 사용되는 전략
- 타입
- template
- 해당 속성에 포함된 모든 하위 속성에 변경이 발생하면 업데이트
- 동작 방식
- label, 버전 마이그레이션 등이 변경되면 파드 업데이트
1-1. 변경된 template 기반의 새로운 ReplicaSet 생성
- ReplicaSet에서 지정된 개수만큼 파드 생성
- 새로운 버전의 ReplicaSet이 파드를 생성했다면 이전 버전의 파드 삭제
3-1. 이전 버전의 ReplicaSet은 롤백에 사용
- Recreate
- 기존 파드를 삭제시킴과 동시에 새로운 ReplicaSet이 파드를 모두 생성
- 처리되는 속도에 따라 기동 시간이 달라짐
- 기동되기 전까지 트래픽을 감당할 수 없으므로 서비스 중단
- RollingUpdate
- 새 버전의 파드 생성
- 기동이 완료되면 이전 버전 파드 삭제
- 반복
- 업데이트 중 서비스 중단이 발생하지 않음
- 대신 업데이트 중 자원 사용량이 150%으로 증가
- 업데이트 중 두 버전이 동시에 호출될 수 있음
- 블루/그린 방식을 통해 해결할 수 있지만 별도 배포 솔루션이 필요하며, 자원 사용량이 200%으로 증가
- RollingUpdate 속성
- maxUnavailable
- 업데이트 동안 최대 몇 개의 파드를 서비스 상태로 유지할 지에 대한 비율
- maxSurge
- 새 버전의 파드를 최대 몇 개까지 동시에 만들지에 대한 비율
- 예시
- maxUnavailable: 100%, maxSurge: 100%
- maxUnavailable로 인해 이전 버전의 모든 파드 중단
- maxSurge로 인해 새 버전의 파드를 replicas 만큼 즉시 생성
- Recreate와 동일한 효과
- maxUnavailable: 0%, maxSurge: 100%
- maxSurge로 인해 새 버전의 파드를 replicas 만큼 즉시 생성
- maxUnavailable로 인해 업데이트 도중 기동 중인 파드를 replicas 만큼 유지
- 애플리케이션마다 기동 시간이 다르므로 새 버전의 파드가 정상적으로 기동하면 이전의 파드 삭제
- 업데이트 도중에도 파드 개수를 replicas를 유지하겠다는 의미
- 자원을 200% 사용하지만 업데이트 시간 단축 및 Blue/Green에 가까운 효과가 발생
- maxUnavailable: 25%, maxSurge: 25%, 이전 버전 파드가 5개 있을 때
- 새 버전으로 업데이트 하기 위해서 25%의 제한에 맞춰 파드 1개 삭제
- 이는 서비스를 제공할 수 있는 파드가 5개에서 4개로 줄어든 것을 의미
- 정상 상태일때보다 트래픽 처리량이 줄어듦
- 이러한 파드의 수가 커지면 커질수록 극대화
실습
RollingUpdate 동작 & 롤백 확인
kubectl patch -n anotherclass-123 hpa api-tester-1231-default -p '{"spec":{"minReplicas":2}}'
kubectl scale -n anotherclass-123 deployment api-tester-1231 --replicas=2
while true; do curl http://192.168.56.30:31231/version; sleep 2; echo ''; done;
kubectl set image -n anotherclass-123 deployment/api-tester-1231 api-tester-1231=1pro/api-tester:v2.0.0
kubectl rollout undo -n anotherclass-123 deployment/api-tester-1231
![](https://velog.velcdn.com/images/appti/post/38388c47-839d-4b74-8f9f-5b477a43f807/image.png)
- 기존 파드, ReplicaSet 상태
- maxUnavailable: 25%, maxSurge: 25%
![](https://velog.velcdn.com/images/appti/post/a9a7aa39-8143-450e-9126-9466bafdcd7b/image.png)
![](https://velog.velcdn.com/images/appti/post/5e91292e-06d7-4754-8428-38bfeae56978/image.png)
- 이미지 업데이트 시 maxSurge에 의해 새 버전의 파드 하나 생성
![](https://velog.velcdn.com/images/appti/post/798d8188-0340-4684-8d0b-1337fabcaf67/image.png)
![](https://velog.velcdn.com/images/appti/post/5821a560-a1dc-4cf2-9416-411a28c9cda6/image.png)
![](https://velog.velcdn.com/images/appti/post/43706ac0-3142-4046-8431-c55a1526ec9b/image.png)
- 새 버전의 파드 하나가 기동
- 새 버전 파드 하나 추가 생성
- 이전 버전 파드 하나 삭제
- 응답을 통해 트래픽을 이전 버전과 새 버전 파드 모두가 처리하고 있음을 확인
![](https://velog.velcdn.com/images/appti/post/958bc2b3-f800-4ae6-9bbb-21786951536a/image.png)
![](https://velog.velcdn.com/images/appti/post/869b038f-1112-42f5-9f6d-8c8ee27aa444/image.png)
![](https://velog.velcdn.com/images/appti/post/f956a55c-0e6e-48e5-8539-c83aedb8ce15/image.png)
- 새 버전의 파드가 replicas 수만큼 생성되고 기동
- 이전 버전 파드 모두 삭제
- 롤백을 위해 이전 버전 replicaSet은 유지
- 응답을 통해 트래픽이 모두 새 버전 파드가 처리하고 있음을 확인
![](https://velog.velcdn.com/images/appti/post/83e54ba1-2faf-4644-a43e-6d39f1de1120/image.png)
![](https://velog.velcdn.com/images/appti/post/e4488d3c-bc1b-4444-a0a9-d06c48e67bf5/image.png)
- 이전 버전 ReplicaSet을 활용해 maxUnavailable, maxSurge의 설정값을 토대로 롤백
- 이전 버전 파드 하나 추가
- 이전 버전 파드는 아직 기동되지 않음
- 새 버전 파드 하나 삭제
![](https://velog.velcdn.com/images/appti/post/35910fc8-14ac-44e2-b7b1-b5678ef6c38a/image.png)
![](https://velog.velcdn.com/images/appti/post/2779ef90-d393-407c-a882-9df965fd10cd/image.png)
![](https://velog.velcdn.com/images/appti/post/e7c40e09-f651-48c3-a2d2-7eed2c2f4306/image.png)
- 이전 버전 파드 하나 기동
- 새 버전 파드 하나 삭제
- 이전 버전 파드 하나 추가적으로 생성
- 응답을 통해 트래픽을 이전 버전과 새 버전 파드 모두가 처리하고 있음을 확인
![](https://velog.velcdn.com/images/appti/post/7a8e3d29-b744-4fc1-b8ed-267ebf38b23b/image.png)
![](https://velog.velcdn.com/images/appti/post/497e42f7-426f-47ab-b27a-ac99915c3e92/image.png)
![](https://velog.velcdn.com/images/appti/post/13f457cf-4dfd-4386-b705-c2fd21b3245c/image.png)
- 이전 버전의 파드가 replicas 수 만큼 생성되고 기동
- 새 버전 파드 모두 삭제
- 새 버전 ReplicaSet 유지
- 응답을 통해 트래픽을 이전 버전의 파드가 모두 처리하고 있음을 확인
maxUnavailable, maxSurge 변경
maxUnavailable: 50%, maxSurge: 50%
![](https://velog.velcdn.com/images/appti/post/f6c9c7b6-22ce-42f0-a7e8-b01506529dc6/image.png)
![](https://velog.velcdn.com/images/appti/post/0599ae36-616b-4805-82ce-b559e26193e7/image.png)
![](https://velog.velcdn.com/images/appti/post/f686480b-e514-47df-b12d-893f1a05a112/image.png)
- 이전 버전 파드 하나 유지
- 새 버전 파드 두 개 생성
![](https://velog.velcdn.com/images/appti/post/44739df9-bc16-4ac9-af20-345b5433e735/image.png)
![](https://velog.velcdn.com/images/appti/post/03988c95-f9cf-46d1-96ab-8975af14bc79/image.png)
- 일시적으로 모든 파드가 트래픽을 처리하고 있음
![](https://velog.velcdn.com/images/appti/post/f5c3b8ff-6f05-4639-8db3-75eaf6f5fc5f/image.png)
![](https://velog.velcdn.com/images/appti/post/8894af8c-14bb-4fec-b279-10d520c4a59c/image.png)
maxUnavailable: 50%, maxSurge: 49%
![](https://velog.velcdn.com/images/appti/post/a6128e14-2dfe-475e-bce0-9afe05071ea5/image.png)
![](https://velog.velcdn.com/images/appti/post/5a41a7c3-cb82-49d8-b05e-032726b07b9f/image.png)
![](https://velog.velcdn.com/images/appti/post/fa508720-519f-4fda-9563-9b270e348879/image.png)
- 이전 버전 파드 하나 유지
- 새 버전 파드 두 개 생성
![](https://velog.velcdn.com/images/appti/post/f7a5d7ba-b584-44a9-be2a-ce534fad5a76/image.png)
![](https://velog.velcdn.com/images/appti/post/5e602b52-6892-4242-9971-a98217d20ba4/image.png)
- 일시적으로 모든 파드가 트래픽을 처리하고 있음
![](https://velog.velcdn.com/images/appti/post/293a6f50-f53f-4379-b896-3df3ecdba93e/image.png)
![](https://velog.velcdn.com/images/appti/post/7118baa9-f68f-4e44-a7b0-a1c7b741de9b/image.png)
maxUnavailable: 50%, maxSurge: 26%
![](https://velog.velcdn.com/images/appti/post/ea8ada07-ccea-4a5b-8bdf-bc13e565afe7/image.png)
![](https://velog.velcdn.com/images/appti/post/72b08fb9-5721-4126-85cd-0ffa86d816c1/image.png)
![](https://velog.velcdn.com/images/appti/post/908e0bcf-f8ee-40d1-b729-f477bebdb765/image.png)
- 이전 버전 파드 하나 유지
- 새 버전 파드 두 개 생성
![](https://velog.velcdn.com/images/appti/post/4b3e5272-beee-48bf-8b0b-fdd904a670c2/image.png)
![](https://velog.velcdn.com/images/appti/post/20d9f497-a0d4-49af-acac-e802498d2b01/image.png)
maxUnavailable: 0%, maxSurge: 100%
![](https://velog.velcdn.com/images/appti/post/8a00b7ab-fe09-4862-a8ad-d517aee9af8e/image.png)
![](https://velog.velcdn.com/images/appti/post/8a6cfe20-3f0d-49d1-88c7-4a9d04a0bcc3/image.png)
![](https://velog.velcdn.com/images/appti/post/2ed51790-7a9f-46ad-8f95-e18155d71f84/image.png)
- maxSurge로 인해 새 버전 파드 2개 생성
- maxUnavailable로 인해 이전 버전 파드를 아무것도 삭제하지 않음
![](https://velog.velcdn.com/images/appti/post/5e5bbf0a-5dc9-4d5d-a7e7-055c0eb340e8/image.png)
![](https://velog.velcdn.com/images/appti/post/68cd83b9-6157-49ed-860c-6df515c91f97/image.png)
- 일시적으로 모든 파드가 트래픽을 처리하고 있음
![](https://velog.velcdn.com/images/appti/post/c350b85d-26cd-4a49-a3a9-066dfc885a4d/image.png)
![](https://velog.velcdn.com/images/appti/post/9d321438-0e13-496f-b380-a134018079fa/image.png)
Recreate 동작 확인
![](https://velog.velcdn.com/images/appti/post/487a005d-5c11-4813-8944-e2c739aa8379/image.png)
![](https://velog.velcdn.com/images/appti/post/dc76f4ef-408d-46ae-b869-7ef0bd77b0ee/image.png)
![](https://velog.velcdn.com/images/appti/post/e2a4866b-aa28-465e-9d03-938eac83a1d7/image.png)
![](https://velog.velcdn.com/images/appti/post/a326ff2e-3331-412a-b7a5-b293b37ab5ae/image.png)
![](https://velog.velcdn.com/images/appti/post/999fc686-6102-425f-a5d6-daa2b8be4278/image.png)
![](https://velog.velcdn.com/images/appti/post/7f7390b0-9096-429e-b115-f902b06ce5cd/image.png)
![](https://velog.velcdn.com/images/appti/post/7f725469-8a72-42fb-b88c-78212421309d/image.png)
Service
![](https://velog.velcdn.com/images/appti/post/07f9b940-5a83-45ca-8db4-4bcd1395ff0b/image.png)
- 역할
- 서비스 퍼블리싱
- 외부 트래픽을 매핑된 파드로 전달하는 기능 제공
- type : NodePort
- 서비스 디스커버리
- 쿠버네티스가 내부 DNS를 통해 서비스의 이름을 API로 호출하는 기능 제공
- 파드 삭제 시 ip가 변경되므로 DNS 사용
- type : ClusterIP
- 서비스 레지스트리
- 파드가 삭제되고 생성될 때 쿠버네티스가 서비스에 호출되는 IP를 제거하고 등록
- 파드에 서비스를 연결하면 ip 설정과 관련해 직접 처리할 필요가 없음
- 로드밸런싱
- 자주 사용되는 패턴
- 애플리케이션의 포트 변경에 서비스가 영향을 받지 않도록 하는 방법
- 파드 컨테이너 정보성 속성인 ports.name / ports.containerPort 사용
- 서비스의 targetPort에 ports.name을 지정해 매핑
HPA
![](https://velog.velcdn.com/images/appti/post/d8cb8fd7-8c71-4d0e-a1c7-7757f4627db0/image.png)
- 속성
- sacleTargetRef : Deployment 지정
- minReplicas : 최소 복제본 개수
- maxReplicas : 최대 복제본 개수
- 해당 파드는 minReplicas와 maxReplicas 범위 내의 개수가 생성될 수 있음
- metrics : 스케일링 조건
- metrics
- requests : 계산을 위한 100% 기준 값
- 컨테이너 내부에 CPU를 70m 사용하고 있다고 가정
- 파드 두개 중 하마나 70m이므로 평균 35% 사용
- 컨테이너 내부에 CPU를 220m(70m + 150m) 사용하고 있다고 가정
- 계산 공식
- 변경될 파드 수 = 현재 파드 수 * (평균 CPU /HPA CPU)
- limits
- 하나의 파드에서 CPU를 사용할 수 있는 비율 제한
- 평균 임계치를 결정하는데 큰 영향을 끼침
- memory
- 애플리케이션 사용 상황에 따라서 변하는 값이지 부하에 따른 변하는 값이 아니므로 거의 사용하지 않는 옵션
- CPU만만으로는 모든 애플리케이션에 대한 부하 상태를 판단하기 어려움
- 큐, DB 커넥션, 스레드 등 애플리케이션에 따라 부하가 가해지고 있는 상태라고 판단하는 기준이 다르기 때문
- 다양한 부하를 체크할 수 있는 별도의 솔루션 사용
- CPU만으로 판단할 수 있다면 HPA만 사용해도 무방
- behavior
- 잦은 스케일링을 방지하기 위함
- 순간적으로 CPU 사용량이 폭증하는 경우를 대비하기 위함
- scaleUp.stabilizationWindowSeconds : 지정한 시간동안 CPU 사용량을 유지할 경우 스케일 아웃 적용
- scaleDown.stabilizationWindowSeconds : 부하가 감소해도 지정한 시간동안 파드 수 유지
- policies.value : 부하가 감소했을 때 파드를 한 번에 삭제하는 것이 아닌 지정한 값만큼만 삭제
![](https://velog.velcdn.com/images/appti/post/f390a139-1850-4fa2-a981-2de49b246c8f/image.png)
- 이상적인 스케일링
- 평균 부하가 꾸준히 증가하다가 임계치를 넘으면 스케일 아웃 적용
- 트래픽이 감소하면서 평균 부하 감소
- 평균 부하가 감소했으므로 스케일 인 적용
- 현실적인 스케일링
- 평균 부하가 급격하게 증가
- CPU가 임계치를 넘겼으므로 스케일 아웃 적용
- 쿠버네티스 self healing에 의해 Error가 발생한 파드 재시작
- 재시작 또는 스케일 아웃이 적용된 파드가 기동이 완료될 때 까지 서비스 중단
- 서비스 안정화
- 평균 부하가 감소했으므로 스케일 인 적용
- 문제
- 미리 예상하지 못한 트래픽이 올 경우 스케일링만으로는 대응이 어려움
- 해결 방안
- 서비스마다 피크 시간을 분석해 미리 자원을 증설
- 대기열 아키텍처 적용
실습
![](https://velog.velcdn.com/images/appti/post/4945d381-e04d-44ed-9a48-6c3bea05901a/image.png)
curl http://192.168.56.30:31231/cpu-load?min=3&thread=5
kubectl top -n anotherclass-123 pods
kubectl get hpa -n anotherclass-123
scaleUp.stabilizationWindowSeconds 적용 시
![](https://velog.velcdn.com/images/appti/post/27a3d559-55fa-47fc-a935-fddf0c2b75ae/image.png)
![](https://velog.velcdn.com/images/appti/post/efedcd67-004f-4987-a386-ab73e64b729c/image.png)
scaleUp.stabilizationWindowSeconds 미적용 시
![](https://velog.velcdn.com/images/appti/post/858ac1d1-d6bf-4c82-bee6-d2e79049861a/image.png)
![](https://velog.velcdn.com/images/appti/post/598b692e-bf10-4d2c-a625-f6f0eae4e1e6/image.png)