7.3.2 디플로이먼트 명세 분석

앞서 디플로이먼트가 애플리케이션의 선언적 업데이트와 롤백이라는 강력한 기능을 제공한다고 말씀드렸습니다. 이러한 마법 같은 일들을 가능하게 하는 것은 바로 잘 정의된 디플로이먼트 명세(Spec) 덕분입니다. 우리가 요리 레시피를 보고 따라 하듯, 쿠버네티스는 이 명세 파일을 읽고 디플로이먼트가 의도한 대로 동작하도록 만듭니다.

디플로이먼트 역시 다른 쿠버네티스 오브젝트와 마찬가지로 YAML(또는 JSON) 형식의 매니페스트 파일을 통해 정의됩니다. 이 파일에는 디플로이먼트의 이름, 레이블과 같은 metadata 정보와 함께, 디플로이먼트의 실제 동작 방식을 규정하는 spec 필드가 포함됩니다. spec 필드 안에는 디플로이먼트의 핵심적인 특징을 나타내는 여러 하위 필드들이 존재하는데요, 이들을 정확히 이해하는 것이 디플로이먼트를 제대로 활용하는 첫걸음입니다.

이번 절에서는 디플로이먼트 명세의 핵심 필드들을 하나씩 살펴보면서, 각 필드가 어떤 의미를 가지고 어떻게 디플로이먼트의 동작에 영향을 미치는지 자세히 알아보겠습니다. 마치 자동차의 엔진룸을 열어보듯, 디플로이먼트의 내부 구조를 함께 탐험해 보시죠.

7.3.2.1 replicas, selector, template

디플로이먼트 명세를 처음 접하시는 분들이라면 “어, 이거 어디서 많이 본 것 같은데?” 라는 생각이 드실 수 있습니다. 맞습니다! 바로 앞서 우리가 배웠던 레플리카셋 명세의 핵심 필드들과 거의 동일한 구조를 가지고 있기 때문입니다. 이는 디플로이먼트가 내부적으로 레플리카셋을 생성하고 관리하여 파드의 복제본 수를 유지하고 업데이트를 진행하기 때문입니다. 즉, 디플로이먼트는 레플리카셋에게 “이런 모습으로, 이만큼의 파드를 관리해줘” 라고 지시하는 역할을 하며, 그 지시의 내용이 바로 이 세 필드에 담겨 있습니다.

  • replicas 필드:이 필드는 디플로이먼트가 궁극적으로 유지하고자 하는 파드의 복제본 수를 지정합니다. 예를 들어 replicas: 3이라고 설정하면, 디플로이먼트는 직간접적으로 3개의 동일한 파드가 항상 실행되도록 보장하려고 노력합니다. 디플로이먼트는 이 replicas 값을 기준으로 새로운 레플리카셋을 생성할 때 해당 레플리카셋이 관리할 파드의 수를 설정합니다. 만약 디플로이먼트의 replicas 값을 변경하면, 디플로이먼트는 현재 활성화된 레플리카셋의 파드 수를 조절하여 새로운 목표치에 맞추려고 시도합니다. 이는 애플리케이션의 스케일링(확장 또는 축소)을 수행하는 가장 기본적인 방법입니다.
  • selector 필드:selector 필드는 디플로이먼트가 어떤 파드들을 자신의 관리 대상으로 삼을지 식별하는 기준이 되는 레이블 셀렉터를 정의합니다. 정확히는, 디플로이먼트가 생성하고 관리하는 레플리카셋들이 이 selector를 사용하여 자신들이 관리해야 할 파드를 찾게 됩니다. 디플로이먼트의 spec.selector는 한번 설정되면 보통 변경할 수 없는(immutable) 경우가 많으니 주의해야 합니다. 만약 selector를 변경해야 한다면, 기존 디플로이먼트를 삭제하고 새로운 selector를 가진 새 디플로이먼트를 생성해야 할 수도 있습니다.이 selector는 뒤이어 나올 template.metadata.labels와 반드시 일치하거나, 최소한 template.metadata.labels가 selector의 조건을 만족해야 합니다. 이 규칙은 레플리카셋에서와 마찬가지로 디플로이먼트에서도 매우 중요합니다. 만약 이 둘이 일치하지 않으면, 디플로이먼트가 생성한 레플리카셋은 자신이 만들어낸 파드를 자신의 관리 대상으로 인식하지 못하여 의도치 않은 동작(예: 무한 파드 생성 시도)을 유발할 수 있습니다.
  • template 필드:template 필드는 디플로이먼트가 새로운 레플리카셋을 생성할 때, 그리고 그 레플리카셋이 새로운 파드를 생성할 때 사용할 파드의 청사진(blueprint)을 정의합니다. 이 필드 안에는 완전한 하나의 파드 명세(metadata와 spec 포함)가 그대로 들어갑니다.
    • template.metadata: 주로 labels가 정의됩니다. 여기에 정의된 레이블은 새로 생성될 파드에 부착되며, 앞서 강조했듯이 디플로이먼트의 spec.selector와 반드시 일치해야 합니다.
    • template.spec: 파드가 어떤 컨테이너를 실행할지(이미지, 포트, 환경 변수, 볼륨 마운트 등)를 상세히 기술합니다.디플로이먼트에서 template 필드의 변경은 매우 중요한 의미를 가집니다. 바로 이 template 필드(예: template.spec.containers[0].image 값 변경)가 변경되면, 디플로이먼트는 이를 ‘새로운 버전으로의 업데이트 요청’으로 인지하고 롤링 업데이트 프로세스를 시작합니다. 즉, template은 디플로이먼트가 관리하는 애플리케이션의 ‘원하는 상태’를 정의하는 핵심 부분이며, 이 상태의 변경이 곧 새로운 리비전(revision)의 생성을 트리거합니다.

이 세 가지 필드는 디플로이먼트가 “어떤 모습의 파드(template)를, 어떤 이름표를 단 것들로 식별하여(selector), 몇 개나(replicas) 유지할 것인가”를 정의하는 기본 뼈대라고 할 수 있습니다. 레플리카셋의 개념을 잘 이해하셨다면 이 부분은 상대적으로 쉽게 받아들이실 수 있을 겁니다.

7.3.2.2 strategy 필드 (RollingUpdate, Recreate)

디플로이먼트의 진정한 강력함은 바로 이 strategy 필드에서 나옵니다. 이 필드는 디플로이먼트가 기존 버전의 파드를 새로운 버전의 파드로 어떻게 교체할 것인지, 즉 업데이트 전략을 정의합니다. 쿠버네티스는 두 가지 주요 업데이트 전략을 제공하며, 기본값은 RollingUpdate입니다.

  • type 필드: 업데이트 전략의 종류를 지정합니다.
    • RollingUpdate (기본값):애플리케이션의 무중단 업데이트를 목표로 하는 전략입니다. 이 전략을 사용하면, 디플로이먼트는 새로운 버전의 파드를 점진적으로 추가하면서 동시에 기존 버전의 파드를 점진적으로 제거합니다. 서비스 중단 없이 안전하게 업데이트를 진행할 수 있어 대부분의 상용 환경에서 권장되는 방식입니다.RollingUpdate 전략을 사용할 때는 다음과 같은 하위 필드를 통해 업데이트 방식을 세밀하게 제어할 수 있습니다. 이 설정들은 spec.strategy.rollingUpdate 하위에 정의됩니다.
      • maxUnavailable: 롤링 업데이트 과정 중에 사용 불가능한 상태가 되어도 되는 파드의 최대 개수 또는 비율을 지정합니다.
        • 정수 값(예: 1)으로 지정하면 절대적인 개수를 의미합니다.
        • 백분율(예: “25%”)로 지정하면 replicas 수에 대한 비율을 의미합니다 (소수점은 올림 처리).
        • 기본값은 보통 “25%”입니다.
        • 예를 들어 replicas: 4이고 maxUnavailable: “25%” (즉, 1개)라면, 업데이트 중에도 최소 3개의 파드는 항상 사용 가능한 상태를 유지하도록 시도합니다. 이 값은 0이 될 수 없습니다 (단, maxSurge가 0보다 클 경우). 너무 작게 설정하면 업데이트가 느려질 수 있고, 너무 크게 설정하면 서비스 안정성에 영향을 줄 수 있습니다.
      • maxSurge: 롤링 업데이트 과정 중에 원래 replicas 수를 초과하여 일시적으로 더 생성될 수 있는 파드의 최대 개수 또는 비율을 지정합니다.
        • 정수 값(예: 1) 또는 백분율(예: “25%”)로 지정할 수 있습니다.
        • 기본값은 보통 “25%”입니다.
        • 예를 들어 replicas: 4이고 maxSurge: “25%” (즉, 1개)라면, 업데이트 중에 최대 5개의 파드가 동시에 실행될 수 있습니다. 이 값은 0이 될 수 있습니다 (단, maxUnavailable이 0보다 클 경우). 이 값을 통해 새 버전의 파드를 빠르게 준비시켜 전환 속도를 높일 수 있지만, 너무 크게 설정하면 클러스터의 자원을 일시적으로 많이 소모할 수 있습니다.

      maxUnavailable과 maxSurge 값은 함께 고려되어야 합니다. 예를 들어, maxUnavailable: 0 이고 maxSurge: 1 이면, 항상 원하는 replicas 수 이상의 파드가 떠 있도록 하면서 하나씩 교체하는 매우 안전한 업데이트가 가능합니다. 반대로, maxUnavailable: 1 이고 maxSurge: 0 이면, 먼저 기존 파드 하나를 줄인 후 새 파드를 띄우게 됩니다 (여전히 replicas 수는 유지하려 함). 이 두 값 모두 0으로 설정될 수는 없습니다 (이 경우 업데이트가 진행될 수 없기 때문입니다).

    • Recreate:이 전략은 훨씬 단순합니다. 기존 버전의 모든 파드를 먼저 종료시킨 후, 새로운 버전의 모든 파드를 한 번에 생성합니다.이 방식의 가장 큰 단점은 업데이트 과정 중에 명확한 다운타임(downtime)이 발생한다는 것입니다. 모든 구 버전 파드가 사라지고 새 버전 파드가 준비될 때까지 서비스는 응답할 수 없습니다.따라서 Recreate 전략은 일반적으로 프로덕션 환경에서는 잘 사용되지 않습니다. 하지만 다음과 같은 특정 상황에서는 유용할 수 있습니다.
      • 상태를 가진(stateful) 애플리케이션 중에서 동시에 여러 버전이 실행되면 데이터 정합성 등에 문제가 생길 수 있는 경우.
      • 개발 환경에서 리소스가 매우 제한적이거나, 매우 빠른 애플리케이션 교체가 필요하고 짧은 다운타임을 감수할 수 있는 경우.Recreate 전략을 사용하면 rollingUpdate 하위의 maxUnavailable, maxSurge 설정은 무시됩니다.

이 strategy 필드를 통해 우리는 애플리케이션의 특성과 서비스 요구사항에 맞춰 최적의 업데이트 방식을 선택하고 미세 조정할 수 있습니다. 대부분의 경우 RollingUpdate의 기본 설정을 사용해도 충분하지만, 필요에 따라 이 값들을 조절하여 더욱 안정적이거나 빠른 배포를 구현할 수 있다는 점을 기억해두세요.

7.3.2.3 revisionHistoryLimit 필드

디플로이먼트의 또 다른 중요한 기능은 바로 롤백(Rollback)입니다. 새로운 버전을 배포했는데 예상치 못한 문제가 발생했을 때, 이전의 안정적인 버전으로 신속하게 되돌릴 수 있는 능력은 매우 중요합니다. 디플로이먼트는 이러한 롤백을 지원하기 위해 배포 기록(Revision History)을 유지합니다. revisionHistoryLimit 필드는 바로 이 저장할 이전 리비전(revision)의 최대 개수를 지정합니다.

여기서 ‘리비전’이란 디플로이먼트의 template이 변경될 때마다 생성되는 내부적인 버전 기록이라고 생각하시면 됩니다. 각 리비전은 특정 시점의 파드 템플릿 정보를 담고 있으며, 디플로이먼트는 이 정보를 바탕으로 이전 버전의 레플리카셋을 보관합니다.

  • revisionHistoryLimit 필드:
    • 이 필드에 정수 값을 설정하면, 디플로이먼트는 해당 개수만큼의 이전 레플리카셋(즉, 이전 리비전)을 보관합니다.
    • 기본값은 보통 10입니다. 즉, 별도로 설정하지 않으면 최근 10개의 배포 기록이 유지됩니다.
    • 이 값을 0으로 설정하면, 이전 버전의 레플리카셋이 하나도 보관되지 않아 롤백 기능을 사용할 수 없게 됩니다. (정확히는, 마지막으로 성공한 레플리카셋 외에는 정리될 수 있습니다. 따라서 0으로 설정하면 사실상 undo가 불가능해진다고 이해하는 것이 안전합니다.)
    • 예를 들어 revisionHistoryLimit: 3으로 설정하면, 디플로이먼트는 현재 활성화된 레플리카셋 외에 최대 3개의 이전 버전 레플리카셋 정보를 유지합니다. 새로운 업데이트가 발생하여 4번째 이전 리비전이 생기면, 가장 오래된 리비전(레플리카셋)은 자동으로 삭제됩니다.

이 필드의 값을 어떻게 설정하느냐에 따라 다음과 같은 장단점이 있습니다.

  • 값을 크게 설정하면:
    • 장점: 더 많은 과거 버전으로 롤백할 수 있는 유연성이 생깁니다.
    • 단점: 더 많은 이전 레플리카셋 오브젝트가 쿠버네티스의 데이터 저장소(etcd)에 남아있게 되어, 약간의 시스템 리소스를 더 소모할 수 있습니다. (물론 이 레플리카셋들은 파드를 0개로 스케일 다운된 상태이므로 실제 파드 리소스를 점유하지는 않습니다.)
  • 값을 작게 설정하면 (예: 1 또는 2):
    • 장점: etcd에 저장되는 오브젝트 수를 줄여 시스템을 가볍게 유지할 수 있습니다.
    • 단점: 롤백할 수 있는 과거 버전의 선택지가 매우 제한됩니다. 바로 직전 버전으로만 롤백이 가능하거나, 몇 단계 이전으로는 돌아가지 못할 수 있습니다.

일반적으로 기본값인 10은 대부분의 상황에서 적절한 수준입니다. 하지만 서비스의 중요도, 배포 빈도, 롤백의 필요성 등을 고려하여 팀의 정책에 맞게 이 값을 조절할 수 있습니다. 예를 들어, 매우 자주 배포하고 롤백 가능성을 넓게 가져가고 싶다면 값을 조금 더 늘릴 수 있고, 반대로 리소스 관리가 매우 중요하다면 값을 줄일 수도 있습니다.

이 revisionHistoryLimit 필드는 디플로이먼트의 안정적인 운영을 위한 숨은 조력자 같은 역할을 합니다. “만약을 대비한 보험”과도 같으니, 그 의미와 영향을 잘 이해하고 설정하는 것이 좋겠습니다.

지금까지 디플로이먼트 명세의 핵심적인 필드인 replicas, selector, template, 그리고 업데이트 전략을 정의하는 strategy, 마지막으로 롤백을 위한 revisionHistoryLimit에 대해 자세히 알아보았습니다. 이 필드들이 어떻게 상호작용하며 디플로이먼트의 정교한 동작을 만들어내는지 이해하셨다면, 이제 디플로이먼트를 실제 환경에서 자신 있게 활용하실 준비가 되신 겁니다.