k8s revisionHistoryLimit을 이용한 리소스 관리 및 Rollback

k8s 에서는 애플리케이션의 안정적 배포 및 리소스 관리를 위해 다양한 기능을 제공합니다. 그중 revisionHistoryLimit 설정은 배포 시 생성되는 이전 레플리카셋(ReplicaSet)을 관리하는 중요한 기능입니다. 이 설정을 통해 불필요하게 쌓이는 레플리카셋의 수를 제한하여 클러스터 내 리소스를 효율적으로 관리할 수 있으며, Rollback을 수행할 때 필요한 기록을 유지하는 데도 유용합니다.
본 블로그에서는 revisionHistoryLimit 설정을 통한 효율적인 리소스 관리 및 배포 과정에서 발생할 수 있는 Rollback 방법을 알 수 있습니다.

목차

1. revisionHistoryLimit 이란?
2. k8s nginx 배포
3. replicaset History 생성
4. replicaset HIstory를 이용하여 이전 버전 복구
5. 결론

1. revisionHistoryLimit 이란?

revisionHistoryLimit는 Kubernetes에서 중요한 설정 중 하나로, 배포(Deployment)에서 유지할 이전 레플리카셋(ReplicaSet)의 수를 정의합니다. 기본적으로 Kubernetes는 배포가 변경될 때마다 새로운 ReplicaSet을 생성하며, 이 과정에서 ReplicaSet 기록을 관리하기 위해 revisionHistoryLimit을 활용합니다. revisionHistoryLimit의 기본값은 10을 가지고 있습니다.

ReplicaSet의 수가 많아질수록 클러스터 내 노드에 쌓이는 리소스가 증가하게 되므로, 이를 적절히 관리하는 것이 매우 중요합니다. 과도한 ReplicaSet은 클러스터의 성능 저하 및 리소스 낭비를 초래할 수 있기 때문에, revisionHistoryLimit 설정을 통해 효율적인 리소스 관리를 실현하는 것이 바람직합니다.

최적의 revisionHistoryLimit 값을 설정하여 클러스터의 안정성 및 성능을 동시에 확보해야합니다.

2. k8s NGINX 배포

revisionHistory를 사용하여 replicaset History를 생성하기 전에 DeploymentNamespace를 배포합니다.
(revisionHistorydeployment에서만 사용할 수 있습니다.)
revisionHistory는 기본값으로 10을 가지고 있지만 아래 예제에서는 테스트를 위해 5를 지정하였습니다.

# deployment.yaml

  1 apiVersion: apps/v1
  2 kind: Deployment
  3 metadata:
  4   name: nginx-historylimit
  5   namespace: nginx
  6 spec:
  7   revisionHistoryLimit: 5 # 최대 History를 5개까지 저장합니다.
  8   replicas: 2
  9   selector:
 10     matchLabels:
 11       app: nginx-revision
 12   template:
 13     metadata:
 14       labels:
 15         app: nginx-revision
 16     spec:
 17       containers:
 18         - name: nginx
 19           image: nginx:latest
 20           ports:
 21             - containerPort: 80

해당 Deployment에 접속 할 수 있도록 Service를 NodePort type으로 지정한 후 배포합니다.

# service.yaml

  1 apiVersion: v1
  2 kind: Service
  3 metadata:
  4   name: nginx-history-svc
  5   namespace: nginx 
  6 spec:
  7   selector:
  8     app: nginx-revision
  9   ports:
 10     - protocol: TCP 
 11       port: 80
 12       targetPort: 80
 13   type: NodePort

kubectl 명령어를 통해 배포되었는지 확인합니다.

NodePort로 접속하여 배포가 완료되었는지 확인합니다.

3. deployment History 생성

History는 Deployment를 재배포 하거나 Deployment를 수정하여 배포하였을 때 사용하고 있던 Replicaset을 History화 및 새로운 Replicaset을 생성하여 사용하게됩니다.

Deployment를 수정합니다.

# deployment.yaml

  1 apiVersion: apps/v1
  2 kind: Deployment
  3 metadata:
  4   name: nginx-historylimit
  5   namespace: nginx
  6 spec:
  7   revisionHistoryLimit: 5
  8   replicas: 2
  9   selector:
 10     matchLabels:
 11       app: nginx-revision
 12   template:
 13     metadata:
 14       labels:
 15         app: nginx-revision
 16     spec:
 17       containers:
 18         - name: nginx
 19           image: nginx:latest
 20           ports:
 21             - containerPort: 80
22           volumeMounts: # nginx의 구성을 변경하기 위해 configmap을 마운트하여 구성을 변경합니다.
23             - name: nginx-conf-d # 마운트할 볼륨의 이름을 지정합니다.
24               mountPath: /etc/nginx/conf.d # nginx conf.d 경로에 마운트하여 구성을 변경합니다.
25       volumes: # Pod에서 사용할 수 있는 볼륨을 정의합니다.
26         - name: nginx-conf-d # ConfigMap 및 연결된 볼륨의 이름을 지정합니다.
27           configMap: # ConfigMap을 사용하여 외부에서 구성 파일을 관리합니다.
28             name: nginx-conf-d # 마운트할 ConfigMap의 이름을 지정합니다.

Configmap을 배포하여 구성을 변경합니다.

# configmap.yaml

 1 apiVersion: v1
 2 kind: ConfigMap
 3 metadata:
 4   name: nginx-conf-d
 5   namespace: nginx
 6 data:
 7   default.conf: |
 8     server {
 9         listen       80;
10         server_name  localhost;
11 
12         location / {
13             proxy_pass http://192.168.201.26/;
14         }
15     }

먼저 Configmap을 배포 후 Deployment를 배포해야합니다. (Configmap을 가져오지 못해 pod가 ContainerCreating 상태에서 멈춤)

아래 명령어를 통하여 nginx Namespace에 있는 Replicaset을 볼 수 있습니다.

kubectl get replicaset -n nginx

위에서 Deployment를 수정하고 재배포했기 때문에 현재 2개의 Replicaset이 있는 것을 볼 수 있습니다.

Replicaset은 위에서 지정 한 것 처럼 Replicaset의 Histroy가 최대 5개까지 생성됩니다.
(현재 사용하고있는 Replicaset + replicaset History 5)

아래와 같이 최대치인 6개 이후 rollout restart를 통해 History를 만들어도 가장 이전 버전인 nginx-historylimit-7fbdbb4c68가 사라지게 되고 새로운 Replicaset이 나오는 것을 볼 수 있습니다.

rollout history 명령어를 사용하여 히스토리를 확인할 수도 있습니다.

kubectl rollout history deployment -n nginx nginx-historylimit

현재 변경 사항이 기록되지 않은 것을 확인할 수 있습니다. 배포나 수정 시 --record 플래그를 사용하여 변경 사항을 저장할 수 있지만, 이 플래그는 추후 삭제될 예정입니다.

대신, 아래 명령어를 사용하여 명령어를 사용하여 변경 사항을 기록할 수 있습니다.

kubectl annotate deployment [deployment] kubernetes.io/change-cause=""

해당 방법은 모두 수동적으로 이루어지기 때문에 CI/CD를 통한 자동화 이외에는 수동적으로 추가하여야 합니다.

이미지 버전을 변경한 후 재배포합니다.

재배포한 후 annotate를 사용하여 변경사항을 추가합니다.

History에서 변경 사항을 확인할 수 있습니다.

4. deployment History를 이용하여 이전 버전 복구

현재 2개의 Replicaset을 가지고있습니다.

구버전 (REVISION 1)

신버전 (REVISION 2,3)

현재 페이지는 Test Page 서버로 프록시될 수 있도록 구성되어 있습니다.

rollout undo를 이용하여 이전버전으로 되돌릴 수 있습니다.

kubectl rollout undo deployment -n nginx nginx-historylimit

아무 매개변수를 넣지 않고 명령어를 쳤을 때는 현재버전의 바로 이전버전인 2 REVISION으로 변경되게 됩니다.

--to-revision 플래그를 이용하여 되돌릴 history를 지정하여 Rollback할 수 있습니다.
(NGINX의 기본페이지를 가지고 있는 revision1로 되돌립니다.)

kubectl rollout undo deployment -n nginx nginx-historylimit --to-rivision=1

사진과 같이 Rollback을 진행하게 되면 현재 사용하고 있었던 replicaset인 7f59d4858f에서 6df8f44cd4로 이전하는 것을 볼 수 있었습니다.

NGINX의 구성도 구버전인 NGINX 메인 페이지를 보여주는 것을 볼 수 있습니다.

롤백을 진행하게 되면 REVISION의 숫자가 변경되기 때문에 변경 사항을 추가하는 것은 매우 중요합니다.

5. 결론

revisionHistoryLimit을 활용하면 Kubernetes에서 배포 시 생성되는 ReplicaSet의 기록을 효율적으로 관리하여 리소스 낭비를 줄일 수 있습니다. 배포를 업데이트하거나 문제가 발생할 때 쉽게 이전 버전으로 Rollback 할 수 있어, 애플리케이션의 안정성을 강화하는 데 유용합니다. 특히 CI/CD 파이프라인에서 버전 관리 및 변경 사항을 기록하는 방식을 함께 적용하면, 필요 시 안정적인 복구가 가능하며 개발 및 운영 효율성도 높아집니다.

kubernetes Ingress controller인 NGINX Ingress Controller의 상업적 버전을 사용해 보시려면 NGINX STORENGINX Plus Ingress Controller를 참고하세요.

NGINX STORE를 통한 솔루션 도입 및 기술지원 무료 상담 신청

* indicates required