디플로이먼트(Deployment)와 서비스(Service)
포스트
취소

디플로이먼트(Deployment)와 서비스(Service)

디플로이먼트(Deployment) 소개

파드는 자동으로 배포한다.

현업에서는 일반적으로 서버를 작동시킬 때 파드를 수동으로 배포하진 않는다.
디플로이먼트(Deployment)라는 걸 활용해서 파드를 자동으로 배포한다.

디플로이먼트란?

쿠버네티스에서 파드를 묶음으로 쉽게 관리할 수 있는 기능이다.

디플로이먼트를 사용하는 이유

  • 파드의 수를 지정하는 대로 쉽게 생성할 수 있다.
    • 3개를 요청하든 10개를 요청하든 요청하는 만큼 디플로이먼트가 파드를 알아서 생성해준다.
  • 파드가 비정상적으로 종료된다면, 디플로이먼트가 알아서 새로운 파드를 생성해서 파드의 수를 유지해준다.
  • 동일한 구성의 여러 파드를 일괄적으로 일시 중지, 삭제, 업데이트 하기 쉽다.

디플로이먼트 구조

디플로이먼트는 여러 개의 파드를 레플리카셋(ReplicaSet)으로 묶어서 관리한다.
여기서 레플리카셋(ReplicaSet)은 복제본끼리의 묶음이라는 의미를 가진다.

디플로이먼트 적용하기

우선 서버를 3대 띄운다고 가정했을 때 파드를 만들기 위해 작성했던 spring-pod.yaml을 살펴보자.

apiVersion: v1
kind: Pod
metadata:
  name: spring-pod-1
spec:
  containers:
    - name: spring-container
      image: kubernetes-spring
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 8080

---
apiVersion: v1
kind: Pod
metadata:
  name: spring-pod-2
spec:
  containers:
    - name: spring-container
      image: kubernetes-spring
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 8080

---
apiVersion: v1
kind: Pod
metadata:
  name: spring-pod-3
spec:
  containers:
    - name: spring-container
      image: kubernetes-spring
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 8080

살펴봤을 때 중복되는 코드도 너무 많고, 중복되는 코드때문에 총 코드량이 너무 많아진다.
이를 해결하기 위해 디플로이먼트를 사용하기 위한 yaml 파일인 spring-deployment.yaml 파일을 작성해보자.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: backend-app
  template:
    metadata:
      labels:
        app: backend-app
    spec:
      containers:
        - name: spring-container
          image: kubernetes-spring
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080

우선 apiVersionkind가 달라졌다.
파드에서 디플로이먼트로 바뀌었기 때문에
apiVersionv1에서 app/v1으로 바뀌었고
kindPod에서 Deployment로 바뀌었다.

metadata는 동일하게 해당 리소스의 이름을 적으면 된다.
파드의 정보를 명시하기 위한 spring-pod.yaml에서는 파드임을 구분하기 위해 spring-pod-xxx라고 작성했지만,
디플로이먼트의 정보를 명시하기 위한 spring-deployment.yaml에서는 디플로이먼트임을 구분하기 위해 spring-deployment라고 작성했다.

spec 부분은 약간 어렵다.
spec.replicas는 파드의 개수를 의미한다. 이 옵션의 개수에 따라 생성되는 파드의 개수가 달라진다.
spec.selector.matchLabels.app은 원본이 되는 파드의 이름을 의미한다. 해당 파드를 복제해서 사용한다.
spec.template에는 원본이 대한 파드의 정보를 명시한다.
spec.template.metadata.labels.app에는 원본 파드의 이름을 명시한다.
spec.template.spec에는 원본 파드에 대한 정보를 명시한다. 파드에 대한 yaml 파일을 작성할 때와 동일하게 작성하면 된다.

디플로이먼트 관련 명령어

디플로이먼트 생성하기

사실 쿠버네티스 관련 리소스를 생성하는 명령어는 동일하다.
kubectl apply -f [환경설정 파일명]을 실행하면 된다.

디플로이먼트 확인하기

kubectl get deployment 명령문을 실행하면 된다.

레플리카셋 확인하기

kubectl get replicaset 명령문을 실행하면 된다.

디플로이먼트 삭제하기

kubectl delete deployment [디플로이먼트명] 명령문을 실행하면 된다.

레플리카셋 삭제하기

kubectl replicaset deployment [레플리카셋명] 명령문을 실행하면 된다.
그런데 레플리카셋을 굳이 따로 지울 필요는 없다.
왜냐하면 디플로이먼트를 삭제하면 연결된 레플리카셋이 같이 지워지기 때문이다.

만약에 파드의 개수를 바꾸고 싶다면 어떻게 해야할까?

그저 디플로이먼트에 대한 환경설정 파일에 가서 spec.replicas의 숫자를 바꾸면 된다.
그리고 kubectl apply -f [디플로이먼트 환경설정 파일명]을 실행하면 자동으로 반영된다.
실제로 kubectl get pods를 실행해보면 파드의 개수가 변경된 것을 알 수 있다.

셀프 힐링 (Self-Healing)

쿠버네티스에서는 셀프 힐링이라는 기능을 제공한다.
이는 파드 내의 컨테이너가 종료되면 자동으로 컨테이너를 재시작하는 것을 의미한다.
실제로 docker ps를 통해서 실행 중인 컨테이너를 확인하고
아무 컨테이너나 1개를 지정해서 docker kill을 통해서 강제로 종료시켜보자.
이 때 kubectl get pods를 실행해보면 방금 강제 종료한 컨테이너를 포함하고 있는 파드에 대해서
재시작 횟수를 뜻하는 RESTARTS의 값이 1 증가한 것을 확인할 수 있다.

서비스(Service) 소개

디플로이먼트는 파드를 생성해주기만 한다.

디플로이먼트를 통해 파드를 여러 개 생성하려는 이유가 뭘까?
바로 트래픽이 몰리면 그 요청을 분산하기 위해 파드를 동적으로 생성하기 위해서다.
하지만 디플로이먼트는 단순히 파드를 생성하기만 해준다.
그러면 트래픽을 여러 파드에 분산하려면 어떻게 해야 할까?
그럴 때 사용하는 기술이 바로 쿠버네티스의 서비스(Service)다.

서비스란?

외부로부터 들어오는 트래픽을 받아서 파드에 균등하게 분배해주는 로드밸런서 역할을 하는 기능이다.
즉 외부로부터 요청을 받아서 각 파드에 나눠주는 역할을 한다.
실제 운영 중인 서비스에서는 파드에 요청을 보낼 때 포트 포워딩이나 파드 내에 직접 접근해서 요청을 보내지는 않는다.
쿠버네티스의 서비스를 통해 요청을 보내는 것이 일반적이다.

서비스 구조

서비스 적용하기

우선 서버를 3대 띄운다고 가정했을 때 서비스를 생성하기 위한 spring-service.yaml을 작성해보자.

apiVersion: v1
kind: Service
metadata:
  name: spring-service
spec:
  type: NodePort
  selector:
    app: backend-app
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
      nodePort: 30000

우선 apiVersionkind에는 리소스 종류인 Service와 이를 위한 API 버전인 v1을 명시한다.
그리고 metadata.name에는 해당 서비스의 이름을 명시한다.

spec에는 해당 서비스에 대한 세부 정보가 들어간다.

  • spec.type
    • 서비스의 종류
  • spec.selector.app
    • 디플로이먼트 정보를 작성할 떄 넣었던 원본 파드의 이름
  • spec.ports
    • 서비스와 통신하기 위한 정보
  • spec.ports.protocol
    • 서비스에 접속하기 위한 프로토콜
  • spec.ports.port
    • 쿠버네티스 내부에서 서비스에 접속하기 위한 포트 번호
  • spec.ports.targetPort
    • 매핑하기 위한 파드의 포트 번호를 명시
  • spec.ports.nodePort
    • 외부에서 사용자들이 접근하게 될 포트 번호

spec.type에서 명시하는 서비스의 종류에는 3가지가 있다.

  • NodePort
    • 쿠버네티스 내부에서 해당 서비스에 접속하기 위한 포트를 열고 외부에서 접속 가능하도록 한다.
  • ClusterIP
    • 쿠버네티스 내부에서만 통신할 수 있는 IP 주소를 부여한다.
    • 외부에서는 요청할 수 없다.
  • LoadBalancer
    • 외부의 로드밸런서를 활용해 외부에서 접속할 수 있도록 연결한다.
    • 대표적으로 AWS의 로드밸런서가 해당한다.

서비스 관련 명령어

서비스 생성하기

kubectl apply -f [환경설정 파일명] 명령문을 실행하면 된다.
그러면 환경설정 파일에서 명시한 디플로이먼트에 대해서 서비스가 생성된다.

서비스 조회하기

kubectl get service 명령문을 실행하면 된다.

새로운 버전의 서버로 업데이트 시키기

만약에 기존에 운영 중이던 서비스의 새로운 기능이 만들어져서 배포해야 한다면 어떻게 해야할까?
그럴 때는 디플로이먼트에 대한 정보를 수정하면 된다.
예를 들면 기존 이미지명이 kubernetes-spring:1.0이라고 가정해보자.

그러면 아래와 같은 과정을 거치면 된다.

  1. 프로젝트 다시 빌드하기
  2. 새로운 버전의 이미지 빌드하기
    • 이 때 태그명을 변경하자.
    • kubernetes-spring:1.1이라고 가정한다.
  3. 디플로이먼트 환경설정 파일에 가서 spec.template.spec.containers.image 속성에 방금 만든 이미지의 이름을 적어주면 된다.
  4. 그런 다음에 다시 환경설정 파일을 기반으로 업데이트 해주면 된다.
    • kubectl apply -f [환경설정 파일명]

이제 다시 서버에 접속해보면 아까 변경한 내용이 적용된 것을 확인할 수 있다.

모든 리소스 삭제

kubectl delete all --all 명령문을 사용하면 모든 리소스를 삭제할 수 있다.
하지만 모든 리소스를 삭제한다는 것은 매우 위험하다.
확실하게 모든 리소스를 삭제해도 되는 상황이 아니라면 직접 지정해서 삭제하도록 하자.

오브젝트 (Object)

쿠버네티스에서는 서비스, 디플로이먼트, 파드와 같은 리소스를 보고 오브젝트(Object)라고 부른다.

출처

비전공자도 이해할 수 있는 쿠버네티스 입문/실전

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

파드 (Pod)

컨피그맵(ConfigMap)과 시크릿(Secret)을 활용한 환경변수 관리