쿠버네티스 컨트롤러 객체와 함께 파드 실행하기(with. 디플로이먼트)

김재민·2024년 9월 1일
post-thumbnail

Background


  • 쿠버네티스 Pod 란?(with. Container) 게시글에서 쿠버네티스의 파드 개념과 컨테이너가 어떻게 관리 되는지 정리해 보았다.
  • 이번에는 쿠버네티스 컨트롤러의 개념을 간단히 살펴보고
  • 워크로드 리소스 중 디플로이먼트 컨트롤러를 이용 하여 파드를 실행해 보면서,
    쿠버네티스에서 컨트롤러 객체가 왜 중요한지 정리해 보려 한다.
  • 단, 디플로이먼트의 매니패스트 구조, 디플로이먼트가 관리하는 레플리카셋의 속성 등의 자세한 내용은 다루지 않는다.

1. 컨트롤러(Controller) 객체란?


  • 컨트롤러 객체는 다른 리소스를 관리하는 쿠버네티스 리소스이다.
  • 쿠버네티스에서 컨트롤러는 클러스터의 상태를 관찰하고,
    필요한 경우 쿠버네티스 API 와 통신하여 생성, 삭제, 변경 등을 요청하는 컨트롤 루프이다.
    (컨트롤 루프: 시스템 상태를 조절하는 종료되지 않는 루프)

1-1. 컨트롤러 객체가 왜 필요한가?

🏷️ 컨트롤러 객체를 사용하지 않으면

  • 파드를 배포 하고 싶은 개수 만큼 n번 배포 해야한다.
  • 파드를 스케일링 하고 싶을 때에도 사용자가 직접 유지보수 해야한다.
  • 파드를 배포할 때 어떤 노드에 배포할 지 사용자가 직접 고민 해야한다.
  • 파드 장애 발생 여부도 사용자가 직접 모니터링 하고 새로 배포 해야한다.
  • 예시 외에도 파드만 독립적으로 사용할 경우 유지보수 문제점이 많이 발생한다.
    이는 쿠버네티스 오케스트레이션을 온전히 사용하지 못하는 것을 의미한다.

2. 디플로이먼트(Deployment) 란?


  • 디플로이먼트 컨트롤러는 쿠버네티스에서 파드를 관리(스케일링, 롤링 업데이트 등)하는 워크로드 리소스 중 하나이다.

1-1. 디플로이먼트 구성도

  • 디플로이먼트를 이용하면, 아래 이미지와 같이 파드 여러개를 클러스터 내 노드에 적절히 분산 하여 배치 시킬 수 있다.
  • 즉, 개발자가 파드를 어떤 노드에 배포할 지 직접 고민하지 않아도 된다.

  • 디플로이먼트를 이용하여 파드를 배포 했다면, 혹시 노드 또는 파드에 장애가 발생 하더라도 디플로이먼트와 연관 된 리소스들이 자체적으로 판단하여, 아래와 같이 원래 배포 되었던 파드 개수를 유지하기 위해 자가 수복에 들어간다.


1-2. 디플로이먼트 배포하기

  • 아래와 같이 컨트롤러 객체를 생성하면, 자신을 포함 하여 연관 있는 리소스를 함께 생성한다.
  • hello-kiamol-2 이름의 디플로이먼트를 생성하고 디플로이먼트 객체 목록을 조회해 보자.
# 디플로이먼트 생성
$ kubectl create deployment hello-kiamol-2 --image=kiamol/ch02-hello-kiamol

>> deployment.apps/hello-kiamol-2 created

# 디플로이먼트 객체 목록 조회
$ kubectl get deployment

>> 
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
hello-kiamol-2   1/1     1            1           82m  # --> {디플로이먼트이름}

  • 디플로이먼트 구성도에 있는 레플리카셋 역시 아래와 같이 디플로이먼트만 생성 하였는데 배포 된 것을 볼 수 있다.
  • 레플리카셋 이름은 디플로이먼트 이름에 랜덤 문자열이 suffix 로 추가 되어 상속 된 것을 알 수 있다.
  • 지금은 레플리카셋이 정확히 무엇인지 살피지 않는다.
# 레플리카셋 객체 목록 조회
$ kubectl get replicasets

NAME                        DESIRED   CURRENT   READY   AGE
hello-kiamol-2-7cb44d9bdd   1         1         1       84m  # --> {디플로이먼트이름}-{레플리카셋랜덤문자열}

  • 이어서, 디플로이먼트 배포 시 선언해둔 컨테이너를 실행하는 파드도 생성 된 것을 알 수 있다.
  • 파드 이름은 레플리카셋 이름에 랜덤 문자열이 suffix 로 추가 되어 상속 된 것을 알 수 있다.
# 파드 목록 조회
$ kubectl get pods

>>
NAME                              READY   STATUS    RESTARTS        AGE
hello-kiamol                      1/1     Running   2 (6h15m ago)   20h  # --> 이전에 파드 개념 살펴볼 때 생성 했던 파드
hello-kiamol-2-7cb44d9bdd-j8wnl   1/1     Running   0               76m  # --> 이번에 디플로이먼트 생성할 때 배포 된 파드, {디플로이먼트이름}-{레플리카셋랜덤문자열}-{파드랜덤문자열}

📍 즉, 디플로이먼트만 배포 하면 필요한 파드를 대신 만들어 준다


1-3. 컨트롤러 객체와 관리 대상인 리소스간의 연결성 확인

  • 디플로이먼트, 레플리카셋, 파드는 레이블(Labels)과 셀렉터(Selector) 를 이용하여 연결성을 유지 한다.
  • 아래는 hello-kiamol-2 의 상세 정보이다.
  • 디플로이먼트 정보에서 Selector 를 보면 레이블 중 app 이 hello-kiamol-2 인 리소스를 관리 대상으로 하는 것을 알 수 있다.
# 디플로이먼트 상세 정보 확인
$ kubectl describe deployment hello-kiamol-2

>>
Name:                   hello-kiamol-2   # 디플로이먼트 이름
Namespace:              default
CreationTimestamp:      Sun, 01 Sep 2024 20:24:17 +0900
Labels:                 app=hello-kiamol-2    # 디플로이먼트 레이블 중 app 이라는 key 의 value 는 hello-kiamol-2
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=hello-kiamol-2    # 해당 디플로이먼트는 레이블로 app 이라는 key 를 가지는 리소스들을 관리 대상으로 판별한다.
Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=hello-kiamol-2    # 디플로이먼트를 배포하면서 같이 생성 되는 파드의 레이블 중 app(key) 의 value 를 hello-kiamol-2 로 상속 시킨다.
  Containers:
   ch02-hello-kiamol:
    Image:        kiamol/ch02-hello-kiamol
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   hello-kiamol-2-7cb44d9bdd (1/1 replicas created)
Events:          <none>
  • 아래와 같이 디플로이먼트에서 상속 받은 레이블 값으로 리소스를 탐색할 수 있다.
# hello-kiamol-2 디플로이먼트의 레이블 정보만 조회하기
$ kubectl get deployment hello-kiamol-2 --output jsonpath='{.spec.template.metadata.labels}'
>> {"app":"hello-kiamol-2"}

# 레플리카셋의 레이블 정보 중 app 이 hello-kiamol-2 인 레플리카셋 조회하기
$ kubectl get replicasets -l app=hello-kiamol-2
>>
NAME                        DESIRED   CURRENT   READY   AGE
hello-kiamol-2-7cb44d9bdd   1         1         1       113m

# 파드 레이블 정보 중 app 이 hello-kiamol-2 인 파드 조회하기
$ kubectl get pods -l app=hello-kiamol-2
>>
NAME                              READY   STATUS    RESTARTS   AGE
hello-kiamol-2-7cb44d9bdd-j8wnl   1/1     Running   0          113

3. 파드 유실을 복구하는 과정


  • 위와 같이 Labels 를 통해 리소스 연결성을 유지 한다는 것을 알았다.
  • 이번에는 파드 개수를 유지하는 과정을 간단히 정리해 보자.
  • 레플리카셋에서 파드 3개가 유지 되도록 하였는데, 하나의 파드가 유실된 상황을 가정하겠다.

3-1. Pod 가 유실 되었을 때 복구 되는 과정 도식화

[ Pod 유실 후 복구 순서 ]
1. Pod 가 유실 된다.
2. 유실된 Pod 와 같은 Node 에 있는 Kubelet 이 Pod 유실을 감지한다.
3. Kubelet 이 Pod 유실 상태를 API Server 에게 전달한다.
4. API Server 는 etcd 에 Pod 유실 상태를 업데이트 한다.
5. Replicaset 이 API Server 를 통해 현재 Pod 상태를 감지한다.
(실행 중인 Pod 가 3개보다 적다는 것을 인지)
6. Replicaset 이 API Server 에게 새로운 Pod 생성을 요청한다.
7. API Server 는 전달 받은 Pod 배포 정보를 Scheduler 에게 전달한다.
8. Scheduler 는 Pod 를 어떤 Node 에 배포할 지 결정하고, API Server 에게 배포 명령을 전달한다.
9. API Server 는 결정된 Node 에 위치한 Kubelet 에게 Pod 를 실행 하라고 명령한다.
10. Kubelet 은 해당 Node 에 Pod 를 실행하고 모니터링 한다.
11. Kubelet 이 API Server 에게 Pod 상태를 전달한다.
12. API Server 는 etcd 에 Pod 상태를 업데이트한다.
13. Replicaset 은 API Server 를 통해 Pod 상태를 감지하고 안정화 한다.

🏷️ 위 과정에서 유실 된 파드에 Labels 가 Deployment, Replicaset 에서 상속 받은 값과 동일해야 자가 수복을 진행한다.


3-2. 파드 유실 및 복구 실습

  • 디플로이먼트에 의해 배포 된 파드를 강제로 삭제 하고 새로운 파드가 생성 되는지 확인 해보자.
# Pod 목록 조회
$ kubectl get pods
>> 
NAME                              READY   STATUS    RESTARTS     AGE
hello-kiamol-2-7cb44d9bdd-j8wnl   1/1     Running   0            3h38m

# Deployment 의해 생성된 Pod 삭제
$ kubectl delete pod/hello-kiamol-2-7cb44d9bdd-j8wnl
>> pod "hello-kiamol-2-7cb44d9bdd-j8wnl" deleted

# Pod 목록 한 번 더 조회
$ kubectl get pods
>> 
NAME                              READY   STATUS    RESTARTS     AGE
hello-kiamol-2-7cb44d9bdd-jmjzm   1/1     Running   0            3s

🏷️ 파드 삭제 전/후로 파드 이름을 보면 suffix 로 붙은 파드 랜덤 문자열이 변경 된 것을 확인할 수 있다.
🏷️ 만약 파드의 Labels 값을 강제로 변경하더라도 Selector 에 일치하는 파드가 유실 된 것으로 간주하고 하나의 파드를 추가로 배포 한다. 따라서, 리소스들 끼리 연결된 Lables 는 주의해서 변경 해야한다.


4. 네트워크 트레픽 분산


  • 실습에서 디플로이먼트로 배포한 파드는 웹 애플리케이션이다.
  • 디플로이먼트의 replicas(파드 복제본 수)를 3으로 변경하고, 웹 애플리케이션에 네트워크 트레픽을 보내보자.
# 디플로이먼트의 replicas 수를 3으로 업데이트
$ kubectl scale deployment/hello-kiamol-2 --replicas=3

>> deployment.apps/hello-kiamol-2 scaled

# Pod 목록 조회
>>
$ kubectl get pods
NAME                              READY   STATUS    RESTARTS     AGE
hello-kiamol                      1/1     Running   2 (9h ago)   23h
hello-kiamol-2-7cb44d9bdd-54mbm   1/1     Running   0            9s
hello-kiamol-2-7cb44d9bdd-dxkkg   1/1     Running   0            9s
hello-kiamol-2-7cb44d9bdd-jmjzm   1/1     Running   0            54m
  • 위와 같이 디플로이먼트에 의해 배포된 파드가 3개로 증가 했다.
  • 이전에는 파드 하나를 독립적으로 배포 한 후 파드에 포트 포워딩 하여 접속 했다.
  • 그렇다면, 지금은 세 개의 파드에 모두 포트 포워딩 해야 할까? 그렇지 않다.
  • 디플로이먼트에 포트 포워딩 하면 디플로이먼트 컨트롤러가 관리하는 파드 리소스에 네트워크 트레픽을 분산 시킨다.
# 디플로이먼트에 포트 포워딩
$ kubectl port-forward deployment/hello-kiamol-2 8080:80

# http://localhost:8080 으로 접속

5. 정리


이번에 정리한 내용 말고도 컨트롤러 객체의 훨씬 복잡하고 다양한 내용이 많지만, 쿠버네티스에서 파드를 독릭접으로 잘 사용하지 않고 컨트롤러를 더 많이 이용한다는 느낌을 잡을 수 있는 정도는 됐을 것 같다.
다음 게시글에서는 애플리케이션 매니페스트 정의 방법을 정리해볼 예정이다.

profile
안녕하세요. 데이터 엔지니어 김재민 입니다.

0개의 댓글