ReplicationController

ReplicationController

참고: ReplicaSet을 구성하는 Deployment가 이제 복제(replication)를 설정하는 권장 방법입니다.

ReplicationController는 지정된 수의 Pod 레플리카가 항상 한 번에 실행되도록 보장합니다. 다시 말해, ReplicationController는 Pod 또는 동질(homogeneous) Pod 집합이 항상 정상 상태로 사용 가능함을 보장합니다.

출처: 문서

ReplicationController 작동 방식 (How a ReplicationController works)

Pod가 너무 많으면 ReplicationController가 여분의 Pod를 종료합니다. 너무 적으면 더 많은 Pod를 시작합니다. 수동으로 만든 Pod와 달리, ReplicationController가 유지하는 Pod는 실패, 삭제 또는 종료되면 자동으로 교체됩니다. 예를 들어 커널 업그레이드 같은 파괴적인 유지보수 후에 Pod가 노드에서 다시 생성됩니다. 이런 이유로 애플리케이션이 단일 Pod만 필요하더라도 ReplicationController를 사용해야 해요. ReplicationController는 프로세스 감독자(supervisor)와 유사하지만, 단일 노드의 개별 프로세스를 감독하는 대신 여러 노드에 걸쳐 여러 Pod를 감독합니다.

ReplicationController는 논의에서 종종 "rc"로 줄여 부르며, kubectl 명령의 단축어로도 사용됩니다.

간단한 경우는 하나의 ReplicationController 객체를 만들어 Pod의 한 인스턴스를 무기한 안정적으로 실행하는 것입니다. 더 복잡한 사용 사례는 웹 서버 같은 복제된 서비스의 동일한 레플리카 여러 개를 실행하는 것입니다.

예시 ReplicationController 실행 (Running an example ReplicationController)

이 예시 ReplicationController 구성은 nginx 웹 서버의 복사본 3개를 실행합니다.

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

예시 파일을 다운로드한 다음 이 명령을 실행해 예시 작업을 실행합니다.

kubectl apply -f https://k8s.io/examples/controllers/replication.yaml

출력은 다음과 비슷합니다.

replicationcontroller/nginx created

이 명령으로 ReplicationController의 상태를 확인하세요.

kubectl describe replicationcontrollers/nginx

출력은 다음과 비슷합니다.

Name:        nginx
Namespace:   default
Selector:    app=nginx
Labels:      app=nginx
Annotations:    <none>
Replicas:    3 current / 3 desired
Pods Status: 0 Running / 3 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:       app=nginx
  Containers:
   nginx:
    Image:              nginx
    Port:               80/TCP
    Environment:        <none>
    Mounts:             <none>
  Volumes:              <none>
Events:
  FirstSeen       LastSeen     Count    From                        SubobjectPath    Type      Reason              Message
  ---------       --------     -----    ----                        -------------    ----      ------              -------
  20s             20s          1        {replication-controller }                    Normal    SuccessfulCreate    Created pod: nginx-qrm3m
  20s             20s          1        {replication-controller }                    Normal    SuccessfulCreate    Created pod: nginx-3ntk0
  20s             20s          1        {replication-controller }                    Normal    SuccessfulCreate    Created pod: nginx-4ok8v

여기서 세 개의 Pod가 생성되었지만(이미지를 가져오는 중이라서) 아직 아무것도 실행되지 않았어요. 잠시 후 같은 명령이 다음과 같이 보일 수 있습니다.

Pods Status:    3 Running / 0 Waiting / 0 Succeeded / 0 Failed

ReplicationController에 속한 모든 Pod를 기계가 읽을 수 있는 형태로 나열하려면 다음과 같은 명령을 사용할 수 있어요.

pods=$(kubectl get pods --selector=app=nginx --output=jsonpath={.items..metadata.name})
echo $pods

출력은 다음과 비슷합니다.

nginx-3ntk0 nginx-4ok8v nginx-qrm3m

여기서 셀렉터는 ReplicationController의 셀렉터(kubectl describe 출력에서 볼 수 있는)와 같고, replication.yaml에서는 다른 형태입니다. --output=jsonpath 옵션은 반환된 목록의 각 Pod에서 이름을 가져오는 표현식을 지정합니다.

ReplicationController 매니페스트 작성 (Writing a ReplicationController Manifest)

다른 모든 Kubernetes 구성과 마찬가지로 ReplicationController는 apiVersion, kind, metadata 필드가 필요합니다.

컨트롤 플레인이 ReplicationController에 대해 새 Pod를 만들 때, ReplicationController의 .metadata.name은 그 Pod들의 이름을 짓는 기초의 일부가 됩니다. ReplicationController의 이름은 유효한 DNS 서브도메인 값이어야 하지만, 이는 Pod 호스트네임에 예상치 못한 결과를 만들 수 있어요. 최상의 호환성을 위해 이름은 DNS 라벨에 대한 더 엄격한 규칙을 따라야 합니다.

구성 파일 작업에 대한 일반 정보는 객체 관리를 참고하세요.

ReplicationController는 .spec 섹션도 필요합니다.

Pod 템플릿 (Pod Template)

.spec.template.spec의 유일한 필수 필드입니다.

.spec.templatepod 템플릿입니다. Pod와 정확히 같은 스키마를 가지지만, 중첩되어 있고 apiVersion이나 kind가 없습니다.

Pod에 필요한 필드 외에도, ReplicationController의 pod 템플릿은 적절한 라벨과 적절한 재시작 정책을 지정해야 합니다. 라벨의 경우 다른 컨트롤러와 겹치지 않도록 하세요. pod 셀렉터를 참고하세요.

.spec.template.spec.restartPolicyAlways와 같은 것만 허용되며, 지정하지 않으면 이것이 기본값입니다.

로컬 컨테이너 재시작의 경우 ReplicationControllers는 노드의 에이전트(예: Kubelet)에 위임합니다.

ReplicationController의 라벨 (Labels on the ReplicationController)

ReplicationController 자체도 라벨(.metadata.labels)을 가질 수 있어요. 보통 .spec.template.metadata.labels와 같게 설정합니다. .metadata.labels가 지정되지 않으면 기본적으로 .spec.template.metadata.labels로 설정됩니다. 그러나 다를 수도 있고, .metadata.labels는 ReplicationController의 동작에 영향을 주지 않습니다.

Pod 셀렉터 (Pod Selector)

.spec.selector 필드는 라벨 셀렉터입니다. ReplicationController는 셀렉터와 일치하는 라벨을 가진 모든 Pod를 관리합니다. 자신이 만들거나 삭제한 Pod와 다른 사람이나 프로세스가 만들거나 삭제한 Pod를 구분하지 않습니다. 이 덕분에 ReplicationController가 실행 중인 Pod에 영향을 주지 않고 교체될 수 있어요.

지정된 경우 .spec.template.metadata.labels.spec.selector와 같아야 하며, 그렇지 않으면 API에 의해 거부됩니다. .spec.selector가 지정되지 않으면 .spec.template.metadata.labels로 기본 설정됩니다.

또한 일반적으로 이 셀렉터와 일치하는 라벨을 가진 Pod를 직접, 다른 ReplicationController로, 또는 Job 같은 다른 컨트롤러로 만들면 안 됩니다. 그렇게 하면 ReplicationController가 다른 Pod를 자신이 만든 것으로 생각합니다. Kubernetes는 이를 막지 않습니다.

겹치는 셀렉터를 가진 여러 컨트롤러가 생기게 되면 삭제를 직접 관리해야 합니다(아래 참고).

여러 레플리카 (Multiple Replicas)

.spec.replicas를 동시에 실행하려는 Pod 수로 설정해 몇 개의 Pod를 동시에 실행할지 지정할 수 있어요. 특정 시점에 실행되는 수는 더 높을 수도 낮을 수도 있어요. 예를 들어 레플리카를 방금 늘리거나 줄였거나, Pod가 우아하게 종료되고 교체가 일찍 시작된 경우입니다.

.spec.replicas를 지정하지 않으면 기본값은 1입니다.

ReplicationControllers 작업 (Working with ReplicationControllers)

ReplicationController와 그 Pod 삭제 (Deleting a ReplicationController and its Pods)

ReplicationController와 모든 Pod를 삭제하려면 kubectl delete를 사용하세요. Kubectl은 ReplicationController를 0으로 스케일하고 각 Pod가 삭제될 때까지 기다린 다음 ReplicationController 자체를 삭제합니다. 이 kubectl 명령이 중단되면 다시 시작할 수 있습니다.

REST API클라이언트 라이브러리를 사용할 때는 단계를 명시적으로 수행해야 합니다(레플리카를 0으로 스케일, Pod 삭제 대기, 그런 다음 ReplicationController 삭제).

ReplicationController만 삭제 (Deleting only a ReplicationController)

Pod에 영향을 주지 않고 ReplicationController를 삭제할 수 있어요.

kubectl을 사용할 때 kubectl delete--cascade=orphan 옵션을 지정하세요.

REST API클라이언트 라이브러리를 사용할 때는 ReplicationController 객체를 삭제할 수 있습니다.

원본이 삭제되면 교체할 새 ReplicationController를 만들 수 있어요. 이전과 새 .spec.selector가 같기만 하면 새 컨트롤러가 이전 Pod를 입양합니다. 그러나 기존 Pod가 새롭고 다른 pod 템플릿과 일치하도록 만들려고는 하지 않습니다. Pod를 통제된 방식으로 새 스펙으로 업데이트하려면 롤링 업데이트를 사용하세요.

ReplicationController에서 Pod 격리 (Isolating pods from a ReplicationController)

Pod의 라벨을 변경해 ReplicationController의 대상 집합에서 Pod를 제거할 수 있어요. 이 기법은 디버깅과 데이터 복구를 위해 Pod를 서비스에서 제거하는 데 사용할 수 있습니다. 이런 방식으로 제거된 Pod는 자동으로 교체됩니다(레플리카 수가 변경되지 않았다고 가정).

일반적인 사용 패턴 (Common usage patterns)

재스케줄링 (Rescheduling)

위에서 언급했듯이, 실행을 유지하려는 Pod가 1개든 1000개든 ReplicationController는 노드 실패나 Pod 종료(예: 다른 제어 에이전트의 동작으로 인한)의 경우에도 지정된 수의 Pod가 존재하도록 보장합니다.

스케일링 (Scaling)

ReplicationController는 replicas 필드를 업데이트해 수동으로 또는 자동 스케일링 제어 에이전트로 레플리카 수를 늘리거나 줄일 수 있게 해줍니다.

롤링 업데이트 (Rolling updates)

ReplicationController는 Pod를 하나씩 교체해 서비스에 대한 롤링 업데이트를 용이하게 하도록 설계되었습니다.

#1353에서 설명하듯이, 권장 접근 방식은 1레플리카로 새 ReplicationController를 만들고, 새(+1) 및 이전(-1) 컨트롤러를 하나씩 스케일한 다음, 이전 컨트롤러가 0레플리카에 도달하면 삭제하는 것입니다. 이는 예상치 못한 실패와 무관하게 Pod 집합을 예측 가능하게 업데이트합니다.

이상적으로 롤링 업데이트 컨트롤러는 애플리케이션 준비 상태(readiness)를 고려하고, 특정 시점에 충분한 수의 Pod가 생산적으로 서비스하고 있는지 보장해야 합니다.

두 ReplicationController는 롤링 업데이트를 촉발하는 것이 보통 이미지 업데이트이기 때문에, 포드의 주요 컨테이너의 이미지 태그 같은 적어도 하나의 구분 라벨을 가진 Pod를 만들어야 합니다.

여러 릴리스 트랙 (Multiple release tracks)

롤링 업데이트가 진행 중일 때 애플리케이션의 여러 릴리스를 실행하는 것 외에도, 여러 릴리스 트랙을 사용해 오랜 기간 또는 지속적으로 여러 릴리스를 실행하는 것이 일반적입니다. 트랙은 라벨로 구분됩니다.

예를 들어 서비스가 tier in (frontend), environment in (prod)인 모든 Pod를 대상으로 할 수 있습니다. 이제 이 tier를 구성하는 복제된 Pod가 10개 있다고 해보세요. 그런데 이 컴포넌트의 새 버전을 '카나리(canary)'로 테스트하고 싶습니다. tier=frontend, environment=prod, track=stable 라벨을 가진 레플리카를 대부분 9로 설정한 ReplicationController와, tier=frontend, environment=prod, track=canary 라벨을 가진 카나리용 1레플리카로 설정한 다른 ReplicationController를 설정할 수 있어요. 이제 서비스는 카나리와 비카나리 Pod를 모두 다룹니다. 하지만 ReplicationControllers를 별도로 건드려 테스트하고 결과를 모니터링하는 등의 작업을 할 수 있습니다.

Services와 함께 ReplicationControllers 사용 (Using ReplicationControllers with Services)

여러 ReplicationController가 단일 서비스 뒤에 있을 수 있어서, 예를 들어 일부 트래픽은 이전 버전으로, 일부는 새 버전으로 갈 수 있습니다.

ReplicationController는 스스로 종료되지 않지만, 서비스만큼 오래 살지는 않을 것으로 예상됩니다. 서비스는 여러 ReplicationController가 제어하는 Pod로 구성될 수 있으며, 서비스의 수명 동안 많은 ReplicationController가 생성되고 파괴될 것으로 예상됩니다(예: 서비스를 실행하는 Pod의 업데이트를 수행하기 위해). 서비스 자체와 그 클라이언트 모두 서비스의 Pod를 유지하는 ReplicationControllers를 인지하지 못한 채 유지되어야 합니다.

복제용 프로그램 작성 (Writing programs for Replication)

ReplicationController가 만든 Pod는 대체 가능하고(fungible) 의미상 동일해야 하지만, 구성은 시간이 지나면서 이질적이 될 수 있어요. 이는 복제된 무상태(stateless) 서버에 분명히 맞지만, ReplicationController는 마스터 선출(master-elected), 샤드(sharded), 작업자 풀(worker-pool) 애플리케이션의 가용성을 유지하는 데도 사용할 수 있습니다. 그런 애플리케이션은 각 Pod 구성의 정적/일회성 맞춤(안티패턴으로 간주됨) 대신, RabbitMQ 작업 큐 같은 동적 작업 할당 메커니즘을 사용해야 합니다. 리소스의 수직 자동 크기 조정(예: cpu나 memory) 같은 수행되는 모든 Pod 맞춤은 ReplicationController 자체와 유사한 다른 온라인 컨트롤러 프로세스가 수행해야 합니다.

ReplicationController의 책임 (Responsibilities of the ReplicationController)

ReplicationController는 원하는 수의 Pod가 자신의 라벨 셀렉터와 일치하고 작동하도록 보장합니다. 현재 종료된 Pod만 수에서 제외됩니다. 미래에는 준비 상태와 시스템에서 사용 가능한 다른 정보가 고려될 수 있고, 교체 정책에 대한 더 많은 제어를 추가할 수 있으며, 외부 클라이언트가 임의로 정교한 교체 및/또는 스케일다운 정책을 구현하는 데 사용할 수 있는 이벤트를 발생시킬 계획입니다.

ReplicationController는 이 좁은 책임에 영원히 제한됩니다. 자체적으로 준비 상태나 활성 상태(liveness) 프로브를 수행하지 않습니다. 자동 스케일링을 수행하는 대신, 외부 오토스케일러(#492에서 논의)가 제어하도록 의도되었으며, 이는 replicas 필드를 변경합니다. ReplicationController에 스케줄링 정책(예: 분산(spreading))을 추가하지 않을 것입니다. 제어되는 Pod가 현재 지정된 템플릿과 일치하는지 검증해서도 안 됩니다. 이는 자동 크기 조정과 다른 자동 프로세스를 방해할 수 있기 때문입니다. 마찬가지로 완료 마감, 순서 의존성, 구성 확장 및 다른 기능은 다른 곳에 속합니다. 심지어 대량 Pod 생성 메커니즘(#170)을 분리할 계획도 있습니다.

ReplicationController는 구성 가능한 빌딩 블록 원시 요소(composable building-block primitive)로 의도되었습니다. 미래에는 더 높은 수준의 API 및/또는 도구가 그 위와 다른 보완 원시 요소 위에 구축되기를 기대합니다. kubectl이 현재 지원하는 "매크로" 연산(run, scale)은 이것의 개념 증명 예시입니다. 예를 들어 Asgard가 ReplicationControllers, 오토스케일러, 서비스, 스케줄링 정책, 카나리 등을 관리하는 것을 상상할 수 있습니다.

API 객체 (API Object)

Replication controller는 Kubernetes REST API의 최상위 리소스입니다. API 객체에 대한 자세한 내용은 ReplicationController API object에서 확인할 수 있습니다.

ReplicationController의 대안 (Alternatives to ReplicationController)

ReplicaSet

ReplicaSet은 새로운 집합 기반 라벨 셀렉터를 지원하는 차세대 ReplicationController입니다. 주로 Deployment가 Pod 생성, 삭제, 업데이트를 조율하는 메커니즘으로 사용합니다. 사용자 지정 업데이트 조율이 필요하거나 업데이트가 전혀 필요하지 않은 경우가 아니라면, Replica Sets를 직접 사용하는 대신 Deployments를 사용하는 것을 권장합니다.

Deployment (권장)

Deployment는 기본 Replica Sets와 그 Pod를 업데이트하는 더 높은 수준의 API 객체입니다. 롤링 업데이트 기능을 원한다면 Deployments를 권장합니다. 선언적이고 서버 측이며 추가 기능이 있기 때문입니다.

베어 Pod (Bare Pods)

사용자가 직접 만든 Pod의 경우와 달리, ReplicationController는 노드 실패나 커널 업그레이드 같은 파괴적인 노드 유지보수의 경우처럼 어떤 이유로든 삭제되거나 종료된 Pod를 교체합니다. 이런 이유로 애플리케이션이 단일 Pod만 필요하더라도 ReplicationController를 사용할 것을 권장합니다. 프로세스 감독자와 비슷하게 생각하되, 단일 노드의 개별 프로세스 대신 여러 노드에 걸친 여러 Pod를 감독한다고 생각하면 됩니다. ReplicationController는 로컬 컨테이너 재시작을 kubelet 같은 노드의 어떤 에이전트에게 위임합니다.

Job

스스로 종료될 것으로 예상되는 Pod(즉 배치 작업)에는 ReplicationController 대신 Job을 사용하세요.

DaemonSet

머신 모니터링이나 머신 로깅 같은 머신 수준 기능을 제공하는 Pod에는 ReplicationController 대신 DaemonSet을 사용하세요. 이 Pod들은 수명이 머신 수명에 묶여 있습니다: Pod는 다른 Pod가 시작되기 전에 머신에서 실행되어야 하고, 머신이 재부팅/종료할 준비가 되면 안전하게 종료될 수 있습니다.

다음 단계 (What's next)

더 알아보기 (Learn more)