본문 바로가기
BackEnd

도커와 쿠버네티스 -K8S (Deployment)

by mizuiro 2024. 11. 14.

1. Deployment

1-1. Deployment 개념

  • 구성 요소
    • ReplicaSet 의 버전을 관리해주는 객체 (컨트롤러)
    • ReplicaSet 내의 pod 들의 배포, 업데이트까지 담당하는 객체

⇒ K8S 에 어떤 pod를 배포한다는 것은 결국 그 pod 의 버전까지 관리해야 하는 경우가 대부분

⇒ 실제로 개발자들이 K8S 를 사용할 때 pod 나 ReplicaSet을 직접 사용하는 경우는 잘 없다

⇒ Deployment를 사용해서 pod 나 ReplicaSEt

⇒ 그러므로 K8S 의 객체를 직접 생성하는 것보다 Deployment의 spec을 작성하고 관리하는 경우가 많아졌다

1-2. Deployment spec 작성

  • ReplicaSet의 spec을 포함하고 있다 그러므로 spec 이 동일하다
  • strategy 가 pod 를 업데이트하는 상황이 발생했을 때 어떤 방식으로 업데이트할 지에 대한 spec을 정의해야 한다
  • Deployment 는 pod 의 업데이트 전략이 핵심적인 기능을 볼 수 있다

1-3. Deployment 업데이트 전략

Recreate

굉장히 단순한 업데이트 방식

모든 pod 를 한번에 교체하는 전략

만약 현재 pod 의 버전이 1.17 이고, 1.20으로 변경된 버전으로 Deployment를 적용하면, 모든 pod를 종료해 버리고, 새로운 버전의 pod로 실행해주는 방식

업데이트 되는 순간 미세한 시차가 존재하겠지만, 동시에 모두 종료되고, 동시에 모두 생성되어서 실행된다

따라서 서비스에 대한 downtime 이 존재할 가능성이 있다

RollingUpdate

K8S 에서 많이 사용되는 전략

안정적인 서비스를 유지하면서 업데이트를 한다

각 pod를 한 번에 종료하지 않고, 각 pod를 순차적을 종료하고 업데이트 하는 전략으로 전체적으로 pod가 종료되서 서비스가 중단되는 상황을 방지하는 전략

이 방식은 서비스를 무중단을 업데이트 할 수 있다는 장점으로 일반적인 상황에서 선호되는 전략이라고 할 수 있다

하지만, RollingUpdate 가 완료되기 전까지는 구버전과 신 버전이 같이 존재함으로, API 설계 시 구버전과 신버전의 응답이 같이 발생하더라도 문제가 발생하지 않도록 호환성 유지하게 하는 것이 중요

1-4. RollingUpdate 전략 분석

업데이트 구간에서 기존의 pod 수보다 하나 더 많아지게 된다

ex)

ReplicaSet 에서 pod 를 3개 운영 중

Deployment 의 RollingUpdate 전략으로 spec을 정의

처음 실행 시 pod는 3개 이고, 항상 3개를 유지하려고 할 때 무중단 업데이트를 진행한다면 서비스 하고 있는 pod 3 개와 업데이티를 진행하는 pod 1개로 운영되고 있게 된다

3 → 4 → 3 (업데이트 구간에서 기존의 pod 수보다 하나 더 많아지게 된다)

그래서 K8S 에서는 업데이트 구간에 pd 가 추가 되거나 줄어들수 있는 pod 의 수를 제어할 수 있는 옵션을 제공하고 있다

⇒ maxSurage

⇒ maxUnavailable

maxSurge

업데이트 하는 동안 pod 가 얼마나 더 (최대한으로) 생성 될 수 있는지 설정하는 옵션

.spec.strategy.rollingUpdate.maxSurge 는 의도한 파드의 수에 대해 생성할 수 있는 최대 파드의 수를 지정하는 선택적 필드이다. 이 값은 절대 숫자(예: 5) 또는 의도한 파드 비율(예: 10%)이 될 수 있다. MaxUnavailable 값이 0이면 이 값은 0이 될 수 없다. 절대 값은 올림해서 백분율로 계산한다. 기본 값은 25% 이다.

예를 들어 이 값을 30%로 설정하면 롤링업데이트 시작시 새 레플리카셋의 크기를 즉시 조정해서 기존 및 새 파드의 전체 갯수를 의도한 파드의 130%를 넘지 않도록 한다. 기존 파드가 죽으면 새로운 래플리카셋은 스케일 업할 수 있으며, 업데이트하는 동안 항상 실행하는 총 파드의 수는 최대 의도한 파드의 수의 130%가 되도록 보장한다

-공식 문서-

maxUnavailable

업데이트 하는 동안 pod가 얼마나 더 (최대한으로) 줄어들 수 있는지 설정하는 옵션

.spec.strategy.rollingUpdate.maxUnavailable 은 업데이트 프로세스 중에 사용할 수 없는 최대 파드의 수를 지정하는 선택적 필드이다. 이 값은 절대 숫자(예: 5) 또는 의도한 파드 비율(예: 10%)이 될 수 있다. 절대 값은 내림해서 백분율로 계산한다. 만약 .spec.strategy.rollingUpdate.maxSurge 가 0이면 값이 0이 될 수 없다. 기본 값은 25% 이다.

예를 들어 이 값을 30%로 설정하면 롤링업데이트 시작시 즉각 이전 레플리카셋의 크기를 의도한 파드 중 70%를 스케일 다운할 수 있다. 새 파드가 준비되면 기존 레플리카셋을 스케일 다운할 수 있으며, 업데이트 중에 항상 사용 가능한 전체 파드의 수는 의도한 파드의 수의 70% 이상이 되도록 새 레플리카셋을 스케일 업할 수 있다.

  • 공식 문서 -

업데이트 구간에서 기존의 pod 수보다 하나가 더 많아지도록 업데이트가 이루어질 수 있도록 하는 경우 (3→ 4 → 3)

⇒ maxSurge: 1, maxUnavailable : 1

따라서 업데이트 구간의 pod 수의 범위 : replicas - maxUnavailable ~ replicas + maxSurge

RollingUpdate 를 replicas - maxUnavailable ~ replicas + maxSurge 로 설정한다면 업데이트 구간 동안 새로운 버전의 pod 는 하나만 더 생성 될 수 잇고, 이와 동시에 기존 버전의 pod는 한 개씩 순차적으로 종료될 수 있음을 예상 할 수 있다

업데이트 구간에는 기존 버전의 pod는 최대한 한 개 까지 종료될 수 있고, 신 버전의 pod는 최대한 한 개까지 생성 될 수 있다는 이 조건을 위배하지 않고 pod의 수를 조절해가면서 update가 진행이 되도록 K8S 가 보장하게 된다

replicas : 3, 이고, 서비스 중인 pod 의 수가 이보다 줄어들지 않도록 하게 한다면 maxUnavailable : 0 으로 설정하면 된다

그리고 두 옵션 모두 0으로 할 수 없다

2. Deployment 실습

2-1. Recreate 옵션

apiVersion: apps/v1
kind: Deployment
metadata:
    name: my-deployemnt
spec:
    replicas: 3
    strategy:
        type: Recreate
    selector:
        matchLabels:
            app: my-app
    template:
        metadata:
            labels:
                app: my-app
        spec:
            containers:
                - name: my-container
                  image: nginx:1.17
  • ReplicaSet ⇒ replicas, selector, template

  • strategy ⇒ 업데이트 전략

  • 실행

kubectl apply -f ex4-1_recreate.yaml
kubectl get pod

image.png

⇒ 결과를 보면 3개의 pod 가 생성된 것을 볼 수 있다

kubectl describe deployment my-deployment
kubectl describe pod my-deployment

실험 1: deployment를 생성하고 난 후 deployment의 container의 종류를 변경하고 재실행 하면 어떻게 될까?

  • 순서

    1. 기본 Depolyment를 실행하여 pod를 생성

    2. Depolyment의 containers.image : niginx:1.17 → nginx:2.0 으로 변경

    3. 변경된 Depolyment를 실행

    4. kubectl get pod 로 상태를 확인하면서 어떻게 변경되는지 확인

    5. pod 들의 image 버전이 어떻게 바뀌었는지 확인

    6. 만약 좀비 pod 가 생성이 되어서 삭제해야 하는 경우

      1. pod를 강제로 삭제해야 함

      2. kubectl delete pod ‘pod 식별자’ —grace-period=0 —force

        —grace-perid : pod 가 종료할 때까지의 대기시간, 0으로 설정하면 대기하지 않음

        —force : 강제로 삭제한다는 의미

  • 실행 결과

      apiVersion: apps/v1
      kind: Deployment
      metadata:
          name: my-deployment
      spec:
          replicas: 3
          strategy:
              type: Recreate
          selector:
              matchLabels:
                  app: my-app
          template:
              metadata:
                  labels:
                      app: my-app
              spec:
                  containers:
                      - name: my-container
                        image: nginx:1.20
    • 변경된 Deployment 실행 및 변경 사항

      kubectl apply -f ex4-1_recreate.yaml

      ⇒ 3개가 한꺼번에 종료가 되고 새로운 3개가 생성되면서 교체가 되었다

    • depolyment 확인

      ⇒ 이름이 같은 이름이므로 새로 교체가 되었다

    • replicaset 확인

      ⇒ 교체가 되었는데 교체 이전의 replicaset은 남아 있다

    • ⇒ 그렇다면 replicaset에 이름을 정해 주면 교체 시 이전의 replicaset이 남아 있지 않게 되는가??*

    • pod 상세 설정 확인

      ⇒ 버전이 1.20으로 변경된 것을 확인 할 수 있다

‼️ recreate 가 적용되어 있어서 모든 pod 가 정지 된 후 새로운 pod로 교체되었다

실험 2: depolyment를 삭제하지 않고, depolyment 내부의 replicaSet을 삭제하면 어떻게 될까?

  • kubectl get replicaset : replicaset의 상태와 이름 확인

  • kubectl delete replicaset my-deployment-7f98df799d : replicaset 삭제

  • 다시 replicaset 상태 확인

⇒ 같은 이름의 replicaset 생성, 즉 삭제되어도 설정 파일의 내용이 같으면 같은 이름으로 생성됨

  • pod 상태 확인

⇒ 이전 pod는 삭제되고, 새로운 pod 생성

‼️ replicaset은 조건이 같으면 새로 생성이 되어도 같은 이름으로 재생성이 된다 또한 서로 상속 받는 관계이므로 하위의 것들은 상위가 변경이 되면 그 변화에 따라 행동을 한다

실험 3: replicas 옵션에 이름을 주면, 파일의 조건이 수정이 되어도 depolyment처럼 하나만 유지가 될까?

  • 앞의 2번의 실험에서 파일의 조건이 수정되면 depolyment는 1개로 그대로이지만, replicaset 은 2개로 늘어났다. 과거의 버전과 현재의 버전 2개로 생성이 되었다

  • 현재 replicaset을 지우면 다시 생성이 되는데 같은 이름으로 재 생성이 된다. 이때 pod들은 이름이 다르게 생성이 된다

  • replicaset 에 이름을 할당하는 방법은?

Kubernetes에서 Deployment는 파드를 관리할 때 자동으로 ReplicaSet을 생성하고, ReplicaSet의 이름은 기본적으로 Deployment 이름에 해시 값을 추가한 형태로 자동 생성됩니다. 즉, DeploymentReplicaSet의 이름을 직접 설정할 수 있는 방법을 제공하지 않으며, 이는 Kubernetes에서 내부적으로 관리되는 부분입니다.

  • chatgpt-

‼️ depolyment에서 관리를 하므로 사용자가 직접 이름을 할당 할 수 없다

2-2. RollingUpdate 옵션

apiVersion: apps/v1
kind: Deployment
metadata:
    name: my-depolyment2
spec:
    replicas: 3
    strategy:
        type: RollingUpdate
        RollingUpdate:
            maxSurge:
            maxUnavailable:
    selector:
        matchLabels:
            app: my-app
        template:
            metadata:
                labels:
                    app: my-app
            spec:
                containers:
                    - name: my-container
                      image: nginx:1.17
  • maxSurge : 자원을 좀 더사용하면서, pod를 더 많이 실행해서 업데이트 구간에서 좀 더 원활하게 업데이트가 되도록 하는 옵션

  • maxUnavailable : 자원이 부족한 상태에서 노드를 빡빡하게 사용하고 있는 상황에서도 업데이트에 지장이 없도록 어느 정도는 기존의 pod 들을 종료시키면서 공간을 확보할 수 있는 pod 수 지정

  • 실행

kubectl apply -f ex4-1_rollingUpdate.yaml
kubectl get pod

실험 1: Recreate 전략 처럼 Deoplyment 의 내부 container 의 설정을 바꾼 후 재실행 하면 어떻게 반응할까?

  • Depolyment의 containers.image : niginx:1.17 → nginx:2.0 으로 변경

  • 실행 결과

⇒ maxSurge : 1, maxUnavailable : 1 이므로 다음과 같다

  • 최소 가용 파드 수: 업데이트 중에 maxUnavailable: 1 설정에 따라 1개의 파드만 비활성화될 수 있으므로, 최소 2개의 파드는 항상 사용 가능한 상태입니다.
  • 최대 가용 파드 수: 정상 상태에서 3개의 파드가 모두 사용 가능하고, 업데이트 중에는 maxSurge: 1 설정으로 인해 1개의 추가 파드가 생성될 수 있으므로, 최대 4개의 파드가 사용 가능한 상태가 될 수 있습니다.

즉, 업데이트 중에는 최소 2개에서 최대 4개의 파드가 사용 가능하게 됩니다.

요약

  • 업데이트 중에 실행되는 총 파드 수: 2개 ~ 4개
  • 업데이트 중에 사용 가능한(가용한) 파드 수: 2개 ~ 4개

2-3. 공통 실험

번외 1: pod의 생성 개수(replicas)를 변경한다면 depolyment는 어떻게 작동할 까?

기존 replicaset만 사용할 때에는 pod의 생성 개수를 변경하면 증가 할 때는 기존 pod는 동작하고 증가 시키는 수 만큼 새로 생성되어서 동작한다

감소 하게 변경 하면 줄어든 pod의 수를 맞추기 위해 남는 pod들을 중지 시킨다

  • 실험 개요

이러한 조건으로 작동하는 replicaset을 Deployment 의 strategy 전략과 맞물린다면, 생성과 삭제 시 전체 파드들을 다 삭제 하고 새로 생성을 할까?

만약 pod 의 개수 설정이 바뀌었다고 모든 pod들을 삭제 후 변경된 수로 다시 생성한다면 비효율적일 것 같은데 과연 어떻게 될지 시도해보자

  1. pod들을 증가시켰을 때

    replicas의 개수가 3에서 5로 증가 시켜서 작동시켜 본다

    • 현재 상태
3개가 잘 돌아가고 있는 중이다

- 5개로 증가 시킨 후 결과

deployment, replicaset는 새로 생성되지 않고, pod들의 개수만 증가 되었다
pod들은 증가한 개수 만큼 새로 추가만 되었다
  1. pod들을 감소 시켰을 때

    replicas의 개수를 5개에서 3개로 감소시킨다

deployment, replicaset는 새로 생성되지 않고, pod들의 개수만 감소 되었다


pod들은 감소 되었다

‼️ replicas의 변경만 있다면 pod의 생성과 추가에는 strategy 전략이 특별하게 적용되지 않는다