반응형
11장: 애플리케이션 배포를 위한 고급 설정
11.1 포드의 자원 사용량 제한
- 클러스터 자원의 활용률을 높이기 위한 Overcommit 사용
11.1.1 컨테이너와 포드의 자원 사용량 제한 : Limit
- Limit: 파드의 컨테이너가 최대로 사용할 수 있는 자원의 상한선
- cgroup 기술을 이용해 CPU, 메모리의 최대 사용량을 제한할 수 있음
- 자원 할당량을 설정하지 않으면 Pod의 컨테이너가 노드의 물리 자원을 모두 사용할 수 있어 노드 자원이 고갈될 수 있음
- cpu: 1000m (밀리코어) = 1개의 CPU 뜻함
- k describe node 명령어
- Non-terminated Pods: 실행 중인 Pod의 자원 할당량
- 따로 설정하지 않아도 kube-system NS Pod에는 기본적으로 CPU와 메모리가 할당됨
- 각 파드의 NS와 이름 및 각 파드들의 요청과 제한량을 확인
- Allocated resources: 해당 노드에서 실행 중인 파드들의 자원 할당량을 모두 더한 값
- ephemeral-storage : Pod 컨테이너 내부의 임시 저장 공간 크기 (사용 가능한 자원으로 취급 됨) , emptyDir, configMap, Secret와 같은 임시 스토리지 공간을 의미한
- Non-terminated Pods: 실행 중인 Pod의 자원 할당량
11.1.2 컨테이너와 포드의 자원 사용량 제한하기 : Request
- Request: 적어도 이 만큼의 자원은 컨테이너에게 보장돼야 한다. 최소한으로 보장받아야 하는 자원을 정해놔야 오버커밋에 의해 다른 컨테이너가 사용량을 침범하는 충돌 문제를 방지할 수 있다.
- Overcommit 통해 실제 물리 자원보다 더 많은 양의 자원을 할당하게 된다.
- 만약 물리자원이 1GB로 한정되어 있을 때
물리자원 1GB 1. A가 500MB 사용하고 있을 땨 B가 750MB 사용하려 시도하면 메모리 충돌 발생 A컴테이너 - limits: 750Mi B컨테이너 - limits: 750Mi 2. rewquest로 500MB를 보장하면 다른 컨테이너의 최소한의 보장량을 침범하지 않게됨 A컴테이너 - limits: 750Mi - requests: 500Mi B컨테이너 - limits: 750Mi - requests: 500Mi
- 만약 물리자원이 1GB로 한정되어 있을 때
- k8s 스케줄러는 requests만큼 여유 있는 노드를 선택해 Pod를 생성함
- 노드의 총 자원보다 더 많은 양의 requests(컨테이너가 보장받아야 하는 최소한의 원)를 할당할 수 없기 때문
- Limits의 합은 노드의 물리 자원의 크기를 초과할 수도 있기 때문에(오버커밋의 원리) Limits를 기준으로 파드를 할당할 수 없음
11.1.3 CPU 자원 사용량의 제한 원리
- A컨테이너가 Requests보다 더 많은 CPU를 사용하고 있는데, B컨테이너가 Request만큼 CPU 사용하려 하면 A에서 CPU throttle 발생
물리자원 1GB 1. A에서 CPU throttle 발생 A컴테이너 - 700m 사용중 - limits: 750m - requests: 500m B컨테이너 - Request만큼 CPU 사용하려 시도 - limits: 750m - requests: 500m
- CPU: 압축가능(compressible)
- Memory: 압출불가능(incompressible)
11.1.4 QoS 클래스와 메모리 자원 사용량 제한 원리
- kubelet이 메모리 부족 감지하면 우선순위가 가장 낮은 파드 종료해 다른 노드로 퇴거(Evict) 수행
- OOM Killer에 의해 파드 컨테이너의 프로세스가 종료되면, 컨테이너는 Pod의 재시작정책(restartPolicy)에 의해 다시 시작됨 (OOM Killer는 프로세스 강제 종료만 하고, 컨테이너 파드를 종료하지는 않음)
- 메모리 부족시 Pod 종료 순서:
- BestEffort → Burstable → Guaranteed
- 메모리 부족시 Pod 종료 순서:
11.1.5 ResourceQuota와 LimitRanger
- ResourceQuota:
- 네임스페이스에서 할당 할 수 있는 자원의 총합을 제한하기 위해 사용
- 네임스페이스에서 생성할 수 있는 리소스의 개수를 제한하기 위해 사용
- apiVersion: v1 kind: ResourceQuota metadata: name: mem-cpu-quota namespace: dev spec: hard: requests.cpu: "1" requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi
- LimitRanger
- 파드의 컨테이너에 CPU, Mem 할당량 설정 안 되어 있을 경우 자동으로 기본 Requests나 Limits 값을 설정
- 파드, 컨테이너의 CPU, Mem, PVC 최솟/최댓값 설정
- 파드 생성 거부에 대한 에러 로그는 레플리카셋에 있음
- Deployment는 ReplicaSet의 메타데이터를 선언적으로 가지고 있을 뿐, 직접 Pod를 생성하지 않음
- RS에서 파드 생성 실패했다고 해서 계속 빠른 속도로 파드 생성하려 시도하지 않음. 지수 함수 간격으로 10초, 20초, 40초, 80초, 160초 주기로 파드 생성 시도함
11.1.6 ResourceQuota, LimitRanger의 원리 : Admission Controller
- Admission Controller
- 사용자의 API 요청이 적절한지 검증하고, 필요에 따라 API 요청을 변형
11.2 쿠버네티스 스케줄링
- 스케줄링: 파드를 생성할 워커노드 선택
11.2.1 포드가 실제로 노드에 생성되기까지의 과정
- SA, RoleBinding 등 파드 생성 요청한 사용자의 인증/인가
- ResourceQuota와 LimitRanger와 같은 어드미션 컨트롤러가 해당 파드 요청 변형(Mutate), 검증(Validate)
- 워커 노드 중 한 곳에 파드 생성
- 스케줄러에 관여하는 컴포넌트
- kube-scheduler: k8s 스케줄러
- etcd: 데이터베이스 역할 담당
- 스케줄러에 관여하는 컴포넌트
11.2.2 포드가 생성될 노드를 선택하는 스케줄링 과정
- 노드 필터링: 파드 할당 할수 있는/없는 노드 필터링
- 노드 스코어링: k8s 내장 로직에 의해 노드 점수 계산
11.2.3 NodeSelector와 Node Affinity, Pod Affinity
- nodeName: 노드 이름 고정으로 설정
- NodeSelector: Label로 설정
- Node Affinity: 복잡한 조건으로 노드 지정 (preferredDuringScheduling…, requiredDuringScheduling…)
- Pod Affinity: 특정 Pod가 존재하는 노드에 함께 배치
- topologyKey: 해당 라벨을 가지는 토폴로지 범위의 노드를 선택
- Pod Anti-Affinity: 특정 Pod와 다른 노드에 배치
11.2.4 Taints와 Tolerations 사용하기
- Taints (얼룩)
- 얼룩을 지정함으로써 해당 노드에 파드 할당 막음
- 효과
- NoSchedule: 파드 스케줄링하지 않음
- NoExecute: 파드 실행 자체 허용하지 않음
- PreferNoSchedule: 가능하면 스케줄링하지 않음
- NoExecute: 해당 노드에서 실행 중인 파드 종료시킴(Tolerations 설정시 파드 종료 안 됨)
- tolerationSeconds: 값을 주면, 해당 시간(초) 동안은 노드에 머무를 수 있음. 이 시간 지나면 파드는 다른 노드로 옮겨감 - kubectl taint nodes node1 key=value:NoSchedule tolerations: - key: "key" operator: "Equal" value: "value" effect: "NoSchedule"
- Tolerations (용인)
- Taints 설정된 노드에도 파드 할당함
- 얼룩이 져도 할당을 용인함
11.2.5 Cordon, Drain 및 PodDistributionBudget
- Cordon: 해당 노드에 새로운 Pod 스케줄 금지
- SchedulingDsabled 표시 됨
- Drain: 노드의 모든 Pod를 다른 노드로 이주시킴(cordon + eviction)
- PodDisruptionBudget(PDB):
- 정상 Pod가 일정 수 이상 유지되도록 강제 재스케줄 방지
- apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: my-app-pdb spec: minAvailable: 2 selector: matchLabels: app: my-app
11.2.6 커스텀 스케줄러 및 스케줄러 확장
- 기본 스케줄러 외에 사용자 정의 스케줄러 구현 가능
- 스케줄러 확장은 스코어링 로직 변경, 스케줄링 정책 조정 등 다양한 방법 존재
11.3 쿠버네티스 애플리케이션 상태와 배포
11.3.1 디플로이먼트를 통해 롤링 업데이트
- 새 ReplicaSet을 생성하고, 기존 ReplicaSet의 Pod를 순차적으로 교체
- 다운타임 없이 업데이트 가능
- maxUnavailable, maxSurge 옵션으로 업데이트 정책 조정 가능
11.3.2 포드의 생애 주기(Lifecycle)
11.3.2.1. 파드의 상태와 생애 주기
- Pod Lifecycle(책 Version)
- Pending: 파드 생성 요청이 API 서버에 의해 승인됐지만, 실제로 생성되지 않음
- Running: 파드에 포함된 컨테이너가 모두 생성돼 정상적으로 실행됨
- Completed: 파드 정상적으로 실행돼 종료됨. 파드 컨테이너의 init 프로세스가 0을 종료코드로 반환
- Error: 정상적으로 실행되지 안흔 상태로 종료됨. 파드 컨테이너의 init 프로세스가 0이 아닌 종료코드 반환했을 때
- Terminating: 파드 삭제/퇴거되기 위해 삭제 상태
- Pod Lifecycle(k8s 공식문서 Version)값의미
Pending 파드가 쿠버네티스 클러스터에서 승인되었지만, 하나 이상의 컨테이너가 설정되지 않았고 실행할 준비가 되지 않았다. 여기에는 파드가 스케줄되기 이전까지의 시간 뿐만 아니라 네트워크를 통한 컨테이너 이미지 다운로드 시간도 포함된다. Running 파드가 노드에 바인딩되었고, 모든 컨테이너가 생성되었다. 적어도 하나의 컨테이너가 아직 실행 중이거나, 시작 또는 재시작 중에 있다. Succeeded 파드에 있는 모든 컨테이너들이 성공적으로 종료되었고, 재시작되지 않을 것이다. Failed 파드에 있는 모든 컨테이너가 종료되었고, 적어도 하나 이상의 컨테이너가 실패로 종료되었다. 즉, 해당 컨테이너는 non-zero 상태로 빠져나왔거나(exited) 시스템에 의해서 종료(terminated)되었다. Unknown 어떤 이유에 의해서 파드의 상태를 얻을 수 없다. 이 단계는 일반적으로 파드가 실행되어야 하는 노드와의 통신 오류로 인해 발생한다.
11.3.2.2. Running 상태 조건
- init 컨테이너: 정의된 모든 Init 컨테이너가 정상 종료(Exit Code 0) 해야 메인 컨테이너 실행 가능
- postStart: 컨테이너가 시작된 후 실행되는 postStart 핸들러가 성공적으로 수행되어야 함
- HTTP: 컨테이너 시작 직후 특정 주소로 HTTP 요청 전송
- Exec: 컨테이너 시작 직후 컨테이너 내부에서 특정 명령어 실행
- livenessProbe, readinessProbe:
- livenessProbe: 컨테이너가 정상적으로 살아 있는지 주기적으로 확인
- Readiness Probe: 컨테이너가 트래픽을 받을 준비가 되었는지 확인
- statupProbe: 컨테이너 시작될 때 수행되는 초기화 작업 완료되었는지 확인
11.3.3 HPA를 활용한 오토스케일링
- metircs-server를 설치해야 오토스케일링 기능 사용할 수 있음
- HPA 트리거 기준:
- CPU 사용률 (targetCPUUtilizationPercentage)
- Memory 사용량 (Custom Metrics 필요)
- 사용자 정의 지표 (Prometheus + Adapter 필요)
반응형
'OPS' 카테고리의 다른 글
DevOps 스터디 - 커스텀 리소스와 컨트롤러 #1 (0) | 2025.06.15 |
---|---|
DevOps 스터디 - 애플리케이션 배포를 위한 고급 설정 #2 (0) | 2025.06.15 |
Athena 특정 일자 LB 엑세스 로그 조회 (0) | 2025.06.15 |
kubectl apply 명령어 동작 원리 (0) | 2025.06.15 |
DevOps 스터디 - 보안을 위한 인증과 인가 - ServiceAccount와 RBAC #3 (심화) (0) | 2025.05.11 |