-
[Kubernetes] 워크로드 리소스 - ReplicationController, ReplicaSet, Deployment공부/데이터 2025. 1. 28. 19:58
쿠버네티스는 ReplicationController와 ReplicaSet과 같은 컨트롤러를 통해 서비스의 안정성과 확장성을 보장합니다. 이 컨트롤러들은 클러스터 내에서 필요한 파드의 수를 자동으로 조절하여 항상 원하는 상태를 유지하도록 합니다.
선언적 구성은 쿠버네티스의 핵심 개념 중 하나입니다. 이는 시스템에게 "어떤 동작을 해라"라고 지시하는 명령형 방식과 달리, "시스템을 어떤 상태로 만들어라"라고 선언하는 방식입니다. 즉, "파드를 3개 만들어라"라고 명령하는 대신 "항상 3개의 파드가 유지되도록 해라"라고 선언하는 것입니다.
ReplicationController
ReplicationController는 쿠버네티스 클러스터 내에서 지정된 수의 파드를 항상 유지하도록 설계된 컨트롤러입니다. 마치 공장에서 제품의 수량을 일정하게 유지하는 것처럼 ReplicationController는 파드의 수를 꾸준히 관리하며 시스템의 안정성과 가용성을 높이는 역할을 수행합니다.
예시
apiVersion: v1 kind: ReplicationController metadata: name: nginx spec: replicas: 3 selector: app: nginx template: metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80
spec.replicas 필드를 통해 원하는 파드의 수를 지정하고 spec.selector를 통해 해당 컨트롤러가 관리할 파드를 선택합니다. 이 때, spec.selector와 spec.template.metadata.labels는 동일해야 합니다.
ReplicaSet
ReplicationController 다음 나온 기능으로 동일한 목적을 가지고 비슷하게 동작합니다. 차이점에 대해선 아래 예시를 보면서 설명합니다.
예시
apiVersion: apps/v1 kind: ReplicaSet metadata: name: frontend labels: app: guestbook tier: frontend spec: # modify replicas according to your case replicas: 3 selector: matchLabels: tier: frontend # 아래와 같은 표현식 가능 # matchExpressions: # - {key: version, operator: In, values: [1.15]} template: metadata: labels: tier: frontend spec: containers: - name: php-redis image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5
ReplicaSet은 ReplicationController보다 label selector에 있어 더 많은 기능을 가지고 있습니다.
- matchLabels
- ReplicationController의 labels와 동일한 기능
- matchExpressions
- 라벨을 보다 더 세밀하게 조정해서 선택할 수 있는 기능
ReplicationController 에는 표현식과 같은 집합 기반의 selector 기능이 없으므로 기능이 더 많은 ReplicaSet을 많이 사용합니다.
Deployment
Deployments는 애플리케이션 워크로드를 실행하기 위한 일련의 파드를 관리하며 일반적으로 상태를 유지하지 않는 애플리케이션에 적합합니다. Deployment는 파드와 ReplicaSets에 대한 선언적인 업데이트를 제공합니다. Deployment에 원하는 상태를 정의하면 Deployment 컨트롤러가 실제 상태를 원하는 상태로 제어된 속도로 변경합니다. 새로운 ReplicaSets를 생성하거나 기존 Deployment를 제거하고 새로운 Deployment로 모든 리소스를 인수하는 방식으로 Deployment를 정의할 수 있습니다.
즉, deployment는 replicaset의 상위 버전이라 볼 수 있고
RollingUpdate
와RollBack
와 같은 기능을 지원합니다.deployment와 replicaset의 핵심 차이점은 다음과 같습니다.
기능 ReplicaSet Deployment 업데이트 전략 단순한 생성/삭제 RollingUpdate, Recreate 등 다양한 전략 지원 자동 롤백 지원하지 않음 지원 Revision History 지원하지 않음 지원 Canary 배포, Blue-green 배포 지원하지 않음 지원 추가 기능 상대적으로 적음 ProgressDeadlineSeconds, MinReadySeconds 등 다양한 기능 제공 사용 사례
Deployment 생성 및 ReplicaSet 관리
Deployment를 생성하여 애플리케이션을 배포하고 Deployment는 내부적으로 ReplicaSet을 관리하며 ReplicaSet은 실제로 Pod를 생성하고 실행합니다.
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80
- 이 예제에서 metadata.name에 지정한 nginx-deployment 라는 이름의 deployment가 생성됩니다.
- deployment는 spce.replicas 필드에 지정한대로 3개의 복제된 파드를 생성하는 Replicaset을 생성합니다.
- .spec.selector 필드는 생성된 Replicaset이 관리할 파드를 찾을 수 있도록 정의합니다. 이 예제에서는 spec.template.metadata.labels에 지정한 app: nginx를 선택합니다.
- .spec.template 필드에는 다음과 같은 하위 필드가 포함되어 있습니다:
- 파드의 label은 .metadata.labels 필드를 사용하여 app: nginx로 지정
- 파드 템플릿의 사양 또는 .spec 필드는 nginx 1.14.2 버전의 이미지를 실행하도록 지정
- 컨테이너 하나를 생성하고 .spec.containers[0].name 필드를 사용하여 nginx로 이름을 지정하고 .spec.containers[0].ports[0] 필드로 컨테이너는 80 포트를 사용하도록 지정
labels이나 selector를 다른 컨트롤러(다른 deployment 및 statefulset 포함)와 겹치지 않도록 해야합니다. 쿠버네티스는 겹치는 것을 막지 않으며 여러 컨트롤러에 겹치는 셀렉터가 있는 경우, 해당 컨트롤러가 충돌하여 예기치 않게 작동할 수 있습니다.
롤아웃 상태 확인 및 관리 (deployment 업데이트)
Deployment의 롤아웃 상태를 모니터링하여 성공적으로 완료되었는지 확인하고 Deployment의 PodTemplateSpec을 업데이트하여 새로운 상태를 선언합니다. 또한 새로운 ReplicaSet이 생성되고 Deployment는 기존 ReplicaSet에서 새로운 ReplicaSet으로 파드를 이동시킵니다. 마지막으로 각 새로운 ReplicaSet은 Deployment의 revision을 업데이트합니다.
Deployment는 업데이트가 진행되는 동안 특정 수의 파드만 다운되도록 합니다. 기본적으로 원하는 파드 수의 75% 이상이 가동되도록 합니다.(최대 25%는 사용할 수 없음) 또한 Deployment는 원하는 파드 수 이상으로 특정 수의 파드만 생성되도록 보장한다. 기본적으로 원하는 파드 수의 최대 125%(최대 25% 급증)까지만 생성되도록 보장합니다.
새 파드를 생성한 다음 이전 파드를 삭제하고 또 다른 새 파드를 생성하는 방식으로 진행합니다. 충분한 수의 새 파드가 생성될 때까지 이전 파드를 삭제하지 않으며 충분한 수의 이전 파드가 삭제될 때까지 새 파드를 생성하지 않습니다.
롤오버 (aka multiple updates in-flight)
deployment 컨트롤러가 새로운 deployment를 관찰할 때마다 원하는 파드를 불러오기 위해 레플리카셋이 생성됩니다. deployment가 업데이트되면 label이 .spec.selector와 일치하지만 템플릿이 .spec.template과 일치하지 않는 파드를 제어하는 기존 replicaset은 축소됩니다. 결국, 새로운 replicaset은 .spec.replicas로 스케일링되고 모든 이전 replicaset은 0으로 스케일링됩니다.
Label selector 업데이트
일반적으로 label selector 기능을 업데이트하는 것은 권장하지 않습니다. API 버전 app/v1에서는 deployment의 label selector가 생성된 후에는 변경할 수 없습니다.
롤백
Deployment의 현재 상태가 안정적이지 않을 경우, 이전 Deployment revision으로 롤백할 수 있습니다. 롤백할 때, Deployment의 revision이 업데이트됩니다.
스케일링
Deployment를 스케일업하여 더 많은 부하를 처리할 수 있도록 할 수 있습니다. 이는 replicas의 수를 변경하여 스케일링 작업을 처리할 수 있습니다. 만약 HorizontalPodAutoscaler(HPA) 가 설정되어 있다면 파드의 CPU 사용률에 따라 실행할 최소/최대 파드 수를 설정할 수도 있습니다.
비례 스케일링
비례 스케일링은 롤링 업데이트가 진행되는 동안 사용자 또는 오토스케일러가 deployment를 확장할 때 발생하는 현상입니다. 롤링 업데이트 중에는 기존 버전의 파드와 새로운 버전의 파드가 동시에 존재하게 되는데, 이때 시스템 부하가 증가하여 추가적인 파드가 필요할 수 있습니다. 비례 스케일링은 새로운 파드를 기존과 새로운 ReplicaSet에 고르게 분산시켜 시스템의 부하를 균형 있게 분산시킵니다. 이를 통해 시스템의 안정성을 유지하고 롤링 업데이트의 성공률을 높입니다.
롤아웃 일시 중지 및 재개
PodTemplateSpec에 여러 수정 사항을 적용하기 위해 롤아웃을 일시 중지할 수 있습니다. 진행 중이던 수정이 완료되면 롤아웃을 재개하여 새로운 롤아웃을 시작합니다. 이렇게 일시 중지된 deployment는 다시 실행하기 전까지 롤백을 할 수 없습니다.
상태확인 (롤아웃 문제 진단)
Deployment의 상태를 확인하여 롤아웃이 중단되었거나 문제가 발생했는지 파악할 수 있습니다.
진행 중
쿠버네티스는 다음 작업 중 하나가 수행되면 deployment를 진행 중인 것으로 표시합니다.
- deployment가 새 레플리카셋을 생성
- deployment가 최신 레플리카셋을 확장
- deployment가 이전 레플리카셋을 축소
- 새 파드가 준비되거나 사용 가능(spec.minReadySeconds 만큼)
완료
쿠버네티스는 다음 작업 중 하나가 수행되면 deployment를 완료된 것으로 표시합니다.
- deployment와 관련된 모든 replica가 지정한 최신 버전으로 업데이트되었으므로 요청한 모든 업데이트가 완료
- deployment와 관련된 모든 replica를 사용할 수 있음
- 이전 replica가 실행되고 있지 않음
실패
배포가 완료되지 않은 상태에서 최신 Replicaset을 배포하려고 할 때 중단될 수 있습니다.
- 할당량 부족
- Readiness probe 실패
- 이미지 pull 실패
- 불충분한 권한
- limit 범위
- 애플리케이션 런타임 구성 오류
spec.progressDeadlineSeconds을 지정해 이 실패를 감지할 수 있습니다. spec.progressDeadlineSeconds는 deployment 컨트롤러가 배포 진행률이 중단되었음을 (배포 상태에서) 표시하기 전에 대기하는 시간(초)을 나타냅니다.
오래된 ReplicaSet 정리
더 이상 필요 없는 오래된 ReplicaSet을 정리하여 리소스를 효율적으로 관리합니다. spec.revisionHistoryLimit 필드를 설정하여 deployment에 대해 유지하려는 이전 replicaset의 수를 지정할 수 있습니다. 기본값은 10입니다.
- 이 필드를 0으로 명시적으로 설정하면 deployment의 모든 기록이 정리되므로 롤백할 수 없음
카나리아 배포
일부 사용자 또는 서버에 릴리스를 롤아웃을 하려는 경우, 카나리아 패턴에 따라 각 릴리스에 대해 하나씩 여러 개의 배포를 만들 수 있습니다.
deployment spec 작성 방법
다른 모든 쿠버네티스 구성과 마찬가지로 .apiVersion, .kind 및 .metadata 필드가 필요합니다.
컨트롤 플레인이 deployment에 대한 새 파드를 생성할 때 deployment의 metadata.name은 해당 파드의 이름을 지정하는 기준이 됩니다. deployment의 이름은 유효한 DNS 서브도메인 값이어야 하지만 파드 호스트 이름을 지정할 때 예기치 않은 결과가 발생할 수 있습니다. 호환성을 위해 DNS 서브도메인 규칙보다 더 제한적인 DNS label의 규칙을 따르는 것이 좋습니다.
DNS 서브도메인 규칙
- 253자 미만
- 소문자 영숫자, '-' 또는 '.'만 포함
- 영숫자 문자로 시작
- 영숫자 문자로 끝
DNS label 이름
- 최대 63자
- 소문자 영숫자 또는 '-'만 포함
- 영숫자 문자로 시작
- 영숫자 문자로 끝
파드 템플릿
spec.template은 필수값인 파드 템플릿입니다. 중첩되어 있고 apiVersion이나 kind가 없다는 점을 제외하면 파드와 동일한 스키마를 가지고 있습니다.
deployment의 파드 템플릿은 파드의 필수 필드 외에도 적절한 label과 적절한 재시작 정책을 지정해야 합니다. label의 경우, 다른 컨트롤러와 겹치지 않도록 주의해야 합니다. 재시작 정책을 지정하지 않으면 기본값인 Always가 spec.template.spec.restartPolicy에 적용됩니다.
Replicas
.spec.replicas는 원하는 파드 수를 지정하는 선택적 필드이며 기본값은 1입니다.
Selector
spec.selector는 deployment가 대상으로 하는 파드의 pod selector를 지정하는 필수 필드입니다. spec.selector는 spec.template.metadata.labels와 일치해야 하며 그렇지 않으면 API에서 거부됩니다.
API 버전 app/v1에서는 spec.selector와 metadata.labels가 설정되지 않은 경우, 기본값이 spec.template.metadata.labels로 설정되지 않으므로 명시적으로 설정해야 합니다. 또한 app/v1에서 deployment를 생성한 후에는 spec.selector가 변경되지 않습니다.
Deployment는 레이블이 일치하는 파드 중에서 다음 두 가지 경우에 파드를 종료할 수 있습니다.
- 템플릿 불일치: 해당 파드의 템플릿이 Deployment의
spec.template
에 정의된 템플릿과 다를 경우. 즉, 파드의 정의가 Deployment의 정의와 일치하지 않을 때 종료됩니다. - 복제본 수 초과: 레이블이 일치하는 파드의 총 수가 Deployment의
spec.replicas
필드에 지정된 복제본 수를 초과할 경우. 즉, 필요한 파드 수보다 더 많은 파드가 존재할 때 초과된 파드를 종료합니다.
반대로, Deployment는 파드의 수가
spec.replicas
에 지정된 수보다 적을 경우,spec.template
에 정의된 템플릿을 사용하여 새로운 파드를 생성합니다.selector가 겹치는 컨트롤러가 여러 개 있는 경우, 컨트롤러가 경합하게 되어 제대로 작동하지 않습니다.
Strategy
spec.strategy는 이전 파드를 새 파드로 교체하는 데 사용되는 전략을 지정합니다. spec.strategy.type은 "Recreate" 또는 "RollingUpdate"이고 기본값은 "RollingUpdate"입니다.
Recreate
새 파드가 생성되기 전 기존 파드가 종료됩니다.
RollingUpdate
롤링 업데이트 방식으로 파드를 업데이트합니다.
maxUnavailable
와maxSurge
를 지정하여 롤링 업데이트 프로세스를 제어할 수 있습니다.- maxUnavailable
- spec.strategy.rollingUpdate.maxUnavailable은 deployment 업데이트 프로세스 중에 중단될 수 있는 최대 파드 수를 지정하는 선택적 필드입니다. 값은 절대값이나 백분율로 설정합니다. 절대값은 백분율에서 반내림하여 계산됩니다. spec.strategy.rollingUpdate.maxSurge가 0인 경우 이 값은 0이 될 수 없고 기본값은 25%입니다.
- maxSurge
- spec.strategy.rollingUpdate.maxSurge는 기존 파드 외에 추가로 생성될 수 있는 최대 파드 수를 지정하는 선택적 필드입니다. 값은 절대값이나 백분율로 설정합니다. 절대값은 백분율에서 반올림하여 계산됩니다. maxUnavailable이 0인 경우 이 값은 0이 될 수 없고 기본값은 25%입니다.
Progress Deadline Seconds
spec.progressDeadlineSeconds는 배포가 진행되기를 기다리는 최대 시간(초)을 지정하는 선택적 필드입니다. 만약 지정된 시간 내에 Deployment의 진행 상태가 변경되지 않으면, 시스템은 Deployment의 진행이 실패했다고 보고합니다. 리소스의 상태에
type: Progressing
,status: "False"
와reason: ProgressDeadlineExceeded
라는 조건으로 표시됩니다. Deployment 컨트롤러는 계속해서 Deployment를 재시도하고 자동 롤백이 구현되었다면 Deployment 컨트롤러는 이러한 조건을 관찰하는 즉시 Deployment를 롤백합니다.기본값은 600초(10분)이고 해당 필드를 지정하는 경우 spec.minReadySeconds보다 커야 합니다.
Min Ready Seconds
spec.minReadySeconds는 새로 생성된 파드가 준비 상태로 유지되어야 하는 최소 시간(초)을 지정하는 선택적 필드입니다. 기본값은 0이고 0으로 설정할 경우, 파드가 준비되는 즉시 사용 가능한 것으로 간주됩니다.
- 파드가 준비된 것으로 간주되는 시점에 대해 자세히 알아보려면 컨테이너 프로브를 참고
Revision History Limit
deployment의 revision 기록은 해당 deployment가 제어하는 replicaset에 저장됩니다.
spec.revisionHistoryLimit은 롤백을 허용하기 위해 유지할 레플리카셋의 수를 지정하는 선택적 필드입니다. 이러한 과거 레플리카셋은 etcd의 리소스를 소비하고 kubectl get rs의 출력을 혼잡하게 만듭니다. 각 deployment의 revision 구성은 해당 replicaset에 저장되므로 과거 replicaset이 삭제되면 해당 deployment revision으로 롤백할 수 없게 됩니다. 기본적으로 과거 replicaset은 10개가 유지됩니다.
이 필드를 0으로 설정하면 모든 과거 ReplicaSet이 정리됩니다.
Paused
spec.paused는 deployment를 일시 중지하고 다시 시작하기 위한 선택적 bool 필드입니다. 일시 중지된 와deployment와 일시 중지되지 않은 deployment의 유일한 차이점은 일시 중지된 deployment의 파드 템플릿 스펙을 변경해도 일시 중지되어 있는 동안에는 새로운 롤아웃이 트리거되지 않는다는 것입니다. deployment는 생성될 때 기본적으로 일시 중지되지 않습니다.
예시
apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment spec: replicas: 3 selector: matchLabels: app: my-app template: metadata: labels: app: my-app spec: containers: - name: my-container image: my-image:latest ports: - containerPort: 80 readinessProbe: httpGet: path: /healthz port: 80 initialDelaySeconds: 5 periodSeconds: 10 minReadySeconds: 10 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 1 progressDeadlineSeconds: 600 revisionHistoryLimit: 5
- replicas: 항상 3개의 Pod를 유지
- selector: Deployment가 관리할 파드를 선택하는 라벨
- template: 파드의 템플릿으로 생성될 파드의 스펙을 정의
- minReadySeconds: 파드가 생성된 후 10초 동안 준비 상태를 유지해야 사용 가능한 것으로 간주
- readinessProbe: 파드의 준비 상태를 확인하는 방법을 정의하며
/healthz
엔드포인트에 HTTP GET 요청을 보내서 응답을 받으면 준비된 것으로 판단 - strategy: Deployment 업데이트 전략을 정의
- type: RollingUpdate: 점진적으로 Pod를 업데이트하는 방식
- rollingUpdate: RollingUpdate 전략에 대한 세부 설정
- maxSurge: 업데이트 중에 추가될 수 있는 최대 Pod 수로 기존 3개에 더해 최대 1개까지 추가될 수 있음
- maxUnavailable: 업데이트 중에 중단될 수 있는 최대 Pod 수 최대 1개의 Pod가 중단될 수 있음
- progressDeadlineSeconds: Deployment가 600초(10분) 동안 진행되지 않으면 실패로 간주
- revisionHistoryLimit: 최근 5개의 버전만 보관
레퍼런스
https://kubernetes.io/ko/docs/concepts/workloads/controllers/replicationcontroller/
https://kubernetes.io/ko/docs/concepts/workloads/controllers/replicaset/
https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#set-based-requirement
https://kubernetes.io/ko/docs/concepts/workloads/controllers/deployment/
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-subdomain-names
- matchLabels