Kubernetes 업그레이드와 유지보수
Kubernetes 업그레이드와 유지보수 (Kubernetes upgrade and maintenance)
최신 상태의 Kubernetes 클러스터를 유지하는 것은 최적의 성능과 보안을 보장하는 데 중요해요. 특히 자체 관리 클러스터, 특히 베어메탈 인프라에서 실행되는 클러스터에서는 더 중요하죠. 정기 업데이트는 유지보수를 위해 일시적으로 노드를 클러스터에서 제거하는 것과 관련된 통제된 다운타임에도 불구하고 기술 부채를 해결하고 비즈니스 위험을 완화하는 데 도움이 돼요. 운영에서 위험을 받아들이는 것에 대한 추가 통찰은 Site Reliability Engineering 책의 "Embracing Risk" 장을 참조하세요.
출처: 문서
본문
정기 업데이트의 중요성 (Importance of Regular Updates)
Kubernetes 업데이트는 기반 Linux 서버에 보안 업데이트 적용, 오작동하는 하드웨어 컴포넌트 교체, 또는 클러스터를 최신 Kubernetes 버전으로 업그레이드 같은 유지보수 작업의 계획과 실행을 포함해요. 이러한 활동은 견고하고 안전한 인프라를 유지하는 데 필수적이에요.
클러스터의 유지보수 작업 (Maintenance Operations in a Cluster)
일반적으로 유지보수 작업은 구조화된 과정에 따라 한 번에 한 노드씩 수행돼요:
- 워크로드 축출(
drain): 워크로드를 갱신할 노드에서 우아하게 이동시켜 원활한 전환 보장 - 작업 수행: 시스템 업데이트나 하드웨어 교체 같은 실제 유지보수 작업 실행
- 노드를 클러스터에 재합류(
uncordon): 갱신된 노드가 클러스터에 재통합되어 책임을 재개할 준비가 됨
이 과정은 전체 업그레이드 기간 동안 워크로드를 중지하거나 다른 클러스터 노드로 마이그레이션해야 해요.
일시적인 PostgreSQL 클러스터 저하 (Temporary PostgreSQL Cluster Degradation)
표준 접근 방식은 서비스 신뢰성을 보장하고 Kubernetes의 자기 치유 능력을 활용하지만, 일시적으로 저하된 클러스터로 운영하는 것이 허용 가능한 시나리오도 있어요. 이는 특히 노드-로컬 스토리지(node-local storage) 에 의존하는 PostgreSQL 클러스터, 즉 스토리지가 PostgreSQL 데이터베이스를 실행하는 Kubernetes 워커 노드에 로컬인 경우에 관련돼요. 노드-로컬 스토리지, 또는 간단히 로컬 스토리지는 성능을 향상하기 위해 사용돼요.
:::note 데이터베이스 파일이 네트워크를 통해 접근 가능한 공유 스토리지에 있다면, 연산자의 기본 자기 치유 동작이 drain 작업 후 다른 노드의 pod가 볼륨을 재사용하는 시나리오를 효율적으로 처리할 수 있어요. 그런 경우 이 문서의 나머지 섹션은 건너뛰어도 돼요. :::
Pod Disruption Budgets
기본적으로 CloudNativePG는 Postgres 클러스터 운영을 보호해요. 노드를 drain해야 하고 그 노드에 클러스터의 프라이머리 인스턴스가 있으면, drain에 앞서 스위치오버가 발생해요. 노드의 인스턴스가 레플리카로 강등되면 drain을 재개할 수 있어요. 단일 인스턴스 클러스터에서는 스위치오버가 불가능하므로, CloudNativePG는 인스턴스가 있는 노드의 drain을 방지해요. 또한 3개 이상의 인스턴스가 있는 클러스터에서는 CloudNativePG가 drain 작업 중 한 번에 하나의 레플리카만 우아하게 종료되도록 보장해요.
각 PostgreSQL Cluster에는 두 개의 연관된 PodDisruptionBudget 리소스가 장착돼 있어요 — kubectl get pdb 명령으로 쉽게 확인할 수 있어요.
모든 프로덕션 Postgres 클러스터에 pod disruption budgets를 활성화한 채 두는 것을 권장해요. 이는 API 레퍼런스에 자세히 설명된 대로 .spec.enablePDB 옵션을 토글해 간편하게 관리할 수 있어요.
개발 또는 테스트용 PostgreSQL 클러스터 (PostgreSQL Clusters used for Development or Testing)
개발 목적으로 사용되는, 종종 단일 인스턴스로 구성된 PostgreSQL 클러스터의 경우 pod disruption budgets를 비활성화하는 것이 필수적이에요. 그렇게 하지 않으면 해당 클러스터를 호스팅하는 노드의 drain이 방지돼요.
다음 예시는 1-인스턴스 개발 클러스터의 pod disruption budgets를 비활성화하는 방법을 보여줘요:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: dev
spec:
instances: 1
enablePDB: false
storage:
size: 1Gi
이 구성은 개발 활동 중 노드 drain에 대한 제한 없이 더 원활한 유지보수 절차를 보장해요.
노드 유지보수 창 (Node Maintenance Window)
:::info[Important] CloudNativePG가 노드 유지보수 창을 계속 지원하지만, 현재는 이전 섹션에서 설명한 대로 pod disruption budgets를 직접 제어하는 것으로 전환할 것을 권장해요. 이 섹션은 주로 하위 호환성을 위해 유지돼요. :::
1.23 릴리스 이전에는 CloudNativePG가 로컬 스토리지를 다룰 때 Kubernetes 업그레이드를 관리하는 선언적 메커니즘이 하나뿐이었어요: 예를 들어 물리 노드의 파티션을 확장하거나 노드 자체를 업데이트하는 동안 표준 자기 치유 절차가 작동하지 않도록 nodeMaintenanceWindow 옵션을 통해 클러스터를 일시적으로 유지보수 모드로 전환해야 했어요.
:::warning 유지보수 창의 기간을 가능한 한 짧게 제한하세요. 이 단계에서는 자기 치유, 롤링 업데이트, Pod disruption budget을 포함한 Kubernetes의 일부 예상 동작이 비활성화되거나 어떤 제한으로 실행돼요. :::
클러스터의 nodeMaintenanceWindow 옵션에는 두 개의 추가 설정이 있어요:
inProgress:
노드 유지보수 창이 현재 진행 중인지 여부를 나타내는 Boolean 값. 기본값은 off예요. 유지보수 창 동안 아래의 reusePVC 옵션이 연산자에 의해 평가돼요.
reusePVC:
유지보수 작업 중 기존 PVC를 재사용할지 여부를 정의하는 Boolean 값. 기본값은 on이에요. 활성화되면 Kubernetes는 노드가 다시 올라올 때까지 기다렸다가 기존 PVC를 재사용해요. PodDisruptionBudget 정책은 일시적으로 제거돼요. 비활성화되면 Kubernetes는 PostgreSQL의 물리 스트리밍 복제에 의존해 다른 노드에서 새 PVC로 Pod 재생성을 강제한 다음, Pod와 함께 이전 PVC를 파괴해요. 이 시나리오는 일반적으로 데이터베이스 크기가 작고, 기다리는 것보다 새 PostgreSQL 인스턴스를 재클론하는 것이 더 짧은 경우가 아니면 권장되지 않아요. 이 동작은 인스턴스가 하나뿐이고 reusePVC가 비활성화된 클러스터에는 적용되지 않아요: 아래 섹션을 참조하세요.
:::note
kubectl drain 명령을 수행할 때 --delete-emptydir-data 옵션을 추가해야 해요.
걱정하지 마세요: 이는 연산자가 내부적으로 사용하는 다른 볼륨을 가리키는 것이지, PostgreSQL 데이터 디렉터리가 아니에요.
:::
:::info[Important]
.spec.enablePDB 필드를 false로 설정해 PodDisruptionBudget 관리를 비활성화할 수 있어요. 그 경우 연산자는 PodDisruptionBudget을 만들지 않고, 이전에 만든 것이 있으면 삭제해요.
:::
reusePVC가 false로 설정된 단일 인스턴스 클러스터 (Single instance clusters with reusePVC set to false)
:::info[Important] 고가용성을 보장하려면 항상 하나보다 많은 인스턴스로 클러스터를 만들 것을 권장해요. :::
reusePVC가 false로 설정된 단일 인스턴스 클러스터에서 유일한 PostgreSQL 인스턴스를 삭제하면 모든 데이터가 손실되는 것을 의미하므로, 유지보수 모드에서도 그러한 인스턴스가 실행될 수 있는 노드의 drain을 사용자가 방지해요.
그러나 그러한 노드에 유지보수가 필요한 경우 두 가지 옵션이 있어요:
reusePVC를 활성화해 다운타임을 수용- 다른 노드에 인스턴스를 복제하고 프라이머리를 스위치오버
데이터베이스 서비스 다운타임이 환경에 수용 가능하다면, 노드 drain은 nodeMaintenanceWindow를 inProgress: true와 reusePVC: true로 설정하는 것만큼 간단해요. 이렇게 하면 원래 PVC가 사용 가능해지는 즉시(예: 노드-로컬 스토리지의 경우 노드가 다시 올라오는 즉시) 인스턴스가 삭제되고 재생성되도록 허용돼요.
그렇지 않으면 클러스터를 스케일업해 다른 노드에 새 인스턴스를 만들고 그 새 인스턴스를 프라이머리로 승격해 유지보수 중인 노드의 원래 인스턴스를 종료해야 해요. 이 경우 유일한 다운타임은 스위치오버 기간이에요.
가능한 접근 방식은:
- 현재 인스턴스가 실행 중인 노드를 cordon 처리.
- 클러스터를 2개 인스턴스로 스케일업. 데이터베이스 크기에 따라 시간이 걸릴 수 있음.
- 새 인스턴스가 실행되는 즉시, 현재 프라이머리가 cordon된 노드에서 실행 중이므로 연산자가 자동으로 스위치오버를 수행.
- 클러스터를 단일 인스턴스로 스케일 다운. 그러면 이전 인스턴스가 삭제됨.
- 이제 이전 프라이머리의 노드를 성공적으로 drain할 수 있으며, 새 프라이머리를 새 노드에서 계속 실행.