개발/backend

[Backend] 쿠버네티스(K8S)를 시작해보자(3) - 워크로드(workload)편(Pod, ReplicaSet, Deployment)

나인에스 2022. 4. 5. 19:07
 

개요

이전글에서 쿠버네티스에 대한 이론적인 내용과 local host에서 테스트 혹은 트레이닝을 위한 환경을 구성 했다면 이번장에서는 워크로드라고 불리는 실제 쿠버네티스에서 구동되는 요소들(Workload Resource)에 대해서 간략하게 알아보고 YAML파일을 이용해서 이를 배포 하는 방법을 알아 보겠습니다.

주의 : 여기서 다루는 내용은 모두 minikube를 이용합니다. 이는 하나의 cluster, 하나의 Node로 구성되어 있기 때문에 multi node, cluster에 관련된 내용은 포함하지 않습니다.

 

워크로드(Workload)

쿠버네티스를 이용할때에 기본적으로 많이 사용되는 Pod, ReplicaSet, Deployment, 3가지의 워크로드 리소스(workloads resource)에 대해서 간략하게 알아보고 YAML을 이용해서 이를 어떻게 배포하고 관리하며 어떤식으로 동작하지는 알아볼 예정입니다. 위의  3가지 워크로드 리소스 외에도 StatefulSets, DaemonSet, Jobs, CronJob등 여러 리소스들이 있지만 이는 추후 활용 예시와 함께 포스팅 하겠습니다.


Pod

Pod는 쿠버네티스에서 관리 및 배포하는 가장 작은 단위의 컴퓨팅 리소스입니다. 일반적으로 Pod하나에 하나의 Container를 할당하는 형식으로 많이 사용되는데 실제 Pod는 여러개의 Container들을 가질수 있는 일종의 최소 단위의 컨테이너 집합이라고 생각하면 됩니다. 따라서, Pod 또한 여러 container들을 하나의 집합으로 관리해서 다른 리소스 들로부터 격리하고 동작을 보장하는 역활도 하고 있습니다. 전통적인 프로그래밍에서 하나의 container내에서 여러 프로세스를 실행 하는 것과 비슷한 개념이라고 할수 있겠죠. 다만, sendbox가 일반화 된 이후에는 하나의 container에서 하나의 프로세스만 실행 하는 것이 일반적인것 처럼 Pod도 마찬가지인거죠.

Pod를 생성하고 실행하는 방법은 여러가지 방법이 있으나 일반적으로 yml파일을 생성해서 해당 파일을 통해서 설정 후 실행합니다.(command를 이용해서 단순하게 실행할 수도 있으나 이는 단순 테스트 혹은 working확인정도의 용도로만 사용됩니다.)

아래 YAML은 nginx:1.14.2 이라는 docker image를 Pod으로 실행하는 YML 예제 입니다.

nginx:1.14.2 image는 "docker pull nginx:1.14.2" 명령어를 이용해서 docker hub에서 다운받을 수 있습니다.
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  labels:
    app: example-pod
spec:
  containers:
  - name: example-pod
    image: nginx:1.14.2		# 사용할 이미지
    ports:
    - containerPort: 80
    livenessProbe:		# 컨테이너 생성후 정상적으로 동작하는지 체크. 실패하는 경우 컨테이너 재시작
      httpGet:			# GET method를 이용해서 컨테이터 동작 체크
        path: /
        port: 80
      initialDelaySeconds: 5	# 초기 실행 딜레이
      timeoutSeconds: 3		# timeout. 기본값은 1초
      periodSeconds: 5		# 재시도 주기 시간. 기본값은 10초
      failureThreshold: 2	# 실패로 간주되는 최대 시간. 기본값은 3초
    readinessProbe:		# 컨테이너가 준비되었는지 체크. 실패하는 경우 Pod에서 제외.
      httpGet:
        path: /
        port: 80
      initialDelaySeconds: 5
      timeoutSeconds: 3
      periodSeconds: 5
      failureThreshold: 2

위의 yml 파일을 아래 command로 실행해서 Pod를 생성/실행 할 수 있습니다.

$>kubectl apply -f example-pod.yml

생성/실행중인 Pod 확인 하기 위한 command.

# Pod 조회
$>kubectl get pod

# running 중인 pod 상태 조회
$>kubectl describe pod/example-pod

위의 command들을 실행 한 결과

Container Status

우리는 컨테이너를 실행하고 해당 컨테이너에서 우리가 원하는 application이 정상적으로 동작하기를 기대합니다. 하지만 간혹 버그가 함께 포함되어 있거나 실수가 있는 경우 컨테이너를 실행은 했으나 정상적으로 동작하지 않는 경우가 있고, 이 경우를 빠르게 캐치해서 수정하기를 원하죠. 위의 yml파일에서 livenessProbe, readinessProbe 두 가지 항목은 컨테이너가 생성, 실행이 된 후 정상적으로 동작하는지 확인을 하는 부분을 자동화 한 내용입니다.

주석에서도 명시한 것처럼 livenessProbe와 readinessProbe는 컨테이너를 실행하고 80 port의 GET method를 이용해서 정상적으로 동작하는지 판단을 합니다. 여기서 두방식에 차이가 있는데 livenessProbe의 경우 만약 문제가 있다면 해당 컨테이너를 재시작하지만 readinessProbe의 경우 실패하면 Pod에서 제외 합니다. 이 두가지를 모두 사용해서 전체 시스템에 영향을 주지 않도록 설정하는 것이 일반적입니다. (물론 컨테이너의 특성에 따라서 서로 다른 설정이 필요하겠죠 ^^)


ReplicaSet

ReplicaSet 은 명시되어 있는 수자의 Pod들의 실행을 유지/관리하는 역활을 합니다. 윗단락에서 다룬 Pod생성을 이용해서 만들어진 Pod는 만약 버그,리소스 등의 문제로 Pod가 사라진다면 해당 Pod는 자동으로 복구가 되지 않습니다. 이는 서버의 오동작을 유발하게 되겠죠. 따라서, ReplicaSet을 이용해서 특정 Pod가 정해진 숫자만큼 복제/실행 하는 것을 유지 할 수 있습니다.

ReplicaSet을 사용 할 때에는 유지/관리 할 Pod를 선택하는 selector, 몇개의 Pod를 유지 할지 결정하는 replicas 숫자 그리고, ReplicaSet이 Pod을 실행할 때에 사용할 template을 설정해야 합니다. selector에 명시되어 있는 Label을 확인해서 Pod를 수를 확인하고 없으면 새로운 Pod를 생성하는 등 설정된 숫자의 Pod를 유지/관리 하게 됩니다.

위와같이 ReplicaSet을 이용하면 손쉽게 scale out을 할 수 있습니다. selector에 일치하는 Pod를 replicas에 적혀있는 숫자만큼 해당 Pod를 복제해서 실행/유지 하기때문에 아주 간단하게 처리가 됩니다. 이때 복제해서 실행되어야 하는 Pod을 Label로 체크하기 때문에 원치않는 Pod가 생성되지 않게 관리/정의 되어야 합니다. 

ReplicaSet 예제

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: example-replicaset
spec:
  replicas: 3
  selector:
    matchLabels:
      app: example-pod
      tier: app
  template:
    metadata:
      labels:
        app: example-pod
        tier: app
    spec:
      containers:
        - name: example-pod
          image: nginx:1.14.2		# 사용할 이미지

실행 결과 확인


Deployment

위에서 본 ReplicaSet의 예제 처럼 ReplicaSet을 그냥 사용하는 경우는 거의 없습니다.(교육을 제외한 실무등 어디에서든...) 여기서 살펴볼 Deployment가 ReplicaSet을 이용해서 Pod을 관리 고, 이들의 History를 관리하기 때문에 Pod의 업데이트, 배치, 롤백, 특정 버전으로 롤백등의 작업을 할 수 있기 때문입니다.

아래 예제 yml파일을 보시면 알 수 있듯이 ReplicaSet과 내용 및 형식이 거의 동일합니다. Deployment는 아래와 같이 작성된 내용을 바탕으로 ReplicaSet을 관리해서 Pod를 유지/관리 하게 되는거죠.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: example-pod
      tier: app
  template:
    metadata:
      labels:
        app: example-pod
        tier: app
    spec:
      containers:
        - name: example-pod
          image: nginx:1.14.2		# 사용할 이미지

실행 결과 확인

Deployment를 실행한 결과

 

Update

또한, 처음 소개에서 말한 것 처럼 History관리를 하기 때문에 아래 예제와 같이 image의 버전을 1.14.2에서 1.13.0으로 변경하고 다시 실행을 하면 변경된 이미지가 모든 Pod에 적용되는 것을 확인 할 수 있고, kubectl get all을 이용해서 상태를 확인해보면 기존 실행된 deployment와 마지막으로 실행되어 현재 적용되어 있는 deployment를 모두 확인할 수 있습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: example-pod
      tier: app
  template:
    metadata:
      labels:
        app: example-pod
        tier: app
    spec:
      containers:
        - name: example-pod
          image: nginx:1.13.0		# 업데이트할 이미지

실행 결과

이미지 버전 업데이트 결과

Deployment가 이미지를 업데이트 할때에 ReplicaSet를 이용해서 업데이트를 하게 됩니다. 새로운 ReplicaSet를 생성/실행해 해당 ReplicaSet이 업데이트 된 이미지를 이용해서 Pod를 생성하고 정상적으로 Pod가 생성된 것을 확인하면 기존에 ReplicaSet로 인해서 생성되어 있던 Pod를 삭제하는 방식으로 업데이트를 하게 됩니다. 이 과정은 deployment의 상태를 kubectl describe 명령어를 통해서 확인이 가능합니다.

History

위에서 한가지 더 언급한 사항이 있습니다. 바로 History 관리입니다. 위의 예제 실행 결과에서 보여지듯이 Deployment는 내부적으로 변경된 상태 History를 모두 기록하게 되어 있습니다.(마치 git 처럼...) 이말은 언제든지 원하는 버전으로 rollback 이 가능하다는 말이 됩니다.

# History 목록 확인
$>kubectl rollout history deploy/{deployment name}

# History 목록에서 직전 버전으로 rollback 
$>kubectl rollout undo deploy/{deployment name}

# History 목록에서 원하는 revision으로 rollback
$>kubectl rollout undo deploy/{deployment name} --to-revision={revision number}

# 주의 : {deployment name} 에 deployment yml파일의 본인이 입력한 metadata의 name을 입력.
#       위의 예제에서는 example-deployment

 

마무리

이번 포스팅에서는 쿠버네티스의 가장 기본적인 요소에 대한 내용과 해당 요소들의 기본 사용법을 알아봤습니다. 여기있는 것들 외에도 DaemonSet, CronJob,Job,StatefulSet , ReplicationController, 등 여러가지가 있지만 이는 프로젝트의 용도에 따라 여러 방법으로 사용될수 있고, 사용법도 기존과 크게 다르지는 않습니다. 다음번 장에서는 실제 application을 배포해서 url을 이용한 서비스 접근을 하기위한 Service, Ingress들에 대해서 알아보겠습니다.

Ref.

https://kubernetes.io/docs/concepts/workloads/

 

Workloads

Understand Pods, the smallest deployable compute object in Kubernetes, and the higher-level abstractions that help you to run them.

kubernetes.io

https://kubernetes.io/docs/concepts/workloads/controllers/

 

Workload Resources

Production-Grade Container Orchestration

kubernetes.io