쿠버네티스 워크로드

이준석·2023년 2월 12일
0

파드 (Pods)

파드란?

파드(Pod)는 쿠버네티스의 배포 가능한 가장 작은 컴퓨팅 유닛이다.
파드는 그 자체로 하나의 논리적인 호스트이다.

파드는 다음을 포함할 수 있다.
마치 도커 컨테이너처럼 파드 내에서 다음 요소들은 격리된다.

  • 하나 이상의 애플리케이션 컨테이너
  • IP 주소
  • 볼륨과 같은 공유 스토리지


쿠버네티스에서는 "워크로드 리소스"를 만들기 위해 YAML 파일과 같은 리소스 정의 파일을 사용하는 것이 보통이다.

워크로드란?

쿠버네티스에서는 "쿠버네티스 상에서 작동되는 애플리케이션"을 의미하며, 클라우드 분야에서는 "어떤 애플리케이션을 실행할 때 필요한 IT 리소스의 집합"이라는 의미로 통용된다.

마찬가지로 파드를 생성하기 위해 파드를 정의할 때 다음과 같은 형태의 YAML 파일을 사용할 수 있다.
다음 YAML을 따라서 만들고 적당한 디렉토리에 simple-pod.yaml로 저장하자.

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

파드 적용하기

위 파드 정의 파일을 실제로 만들기 위해서는 다음 명령을 사용한다.

kubectl apply -f simple-pod.yaml

위 명령을 통해 pod/niginx created라는 결과가 출력되었다면 즉시 명령어 kubectl get pods를 통해 상태를 확인해보자.

STATUS를 통해 컨테이너가 만들어지고(ContainerCreating), 컨테이너가 실행중인(Running) 상태를 확인할 수 있다.

리소스를 삭제하려면 아래와 같은 명령어를 사용한다.

kubectl delete -f simple-pod.yaml



디플로이먼트 (Deployment)

쿠버네티스에서 Deployment는 한글로 번역하지 않는다.
흔히 우리는 배포라고 하면 서비스의 노출을 떠올리지만, 쿠버네티스의 Deployment는 서비스 노출의 의미가 아니다.
쿠버네티스에서의 Deployment는 파드의 교체/배치(placement)와 관련된 명세다.

파드의 진실

쿠버네티스에서는 사실 직접 사용자가 개별 파드를 만들 일이 그리 많지 않다.
왜냐하면 파드는 일시적이고, 언제나 삭제될 수 있음을 감안하고 만들기 때문이다.
예를 들어, 파드가 실행되는 공간인 노드가 만일 실패하는 경우, 그 안에서 실행되는 파드 역시 사용할 수 없게 된다.

사실 컨테이너를 수동으로 만들고 관리하는 것은, 그냥 도커만 단독으로 사용해도 충분히 할 수 있는 일이다.
쿠버네티스의 핵심은 컨테이너를 오케스트레이션하는 것으로, 파드 장애시 자동 복구하거나, 복제하거나 하는 등의 일을 자동으로 처리하는 데에 있다.
AWS로 따지면 ECS(Elastic Container Service)가 하는 일과 비슷하다.
이 둘은, 컨테이너의 로드 밸런싱과 오토 스케일링과 같은 일을 담당한다.

결론적으로 파드는 디플로이먼트, 스테이트풀셋, 데몬셋을 이용해 관리하는 것이 바람직하다.
해당 워크로드 리소스는 파드 템플릿을 항상 포함하고 있다.

아래는 디플로이먼트의 예시이다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    # 여기서부터 파드 템플릿이다
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
    # 여기까지 파드 템플릿이다.

디플로이먼트가 뭔가요? 어떤 일을 할 수 있는 리소스인가요?

디플로이먼트는 파드를 업데이트하기 위한 선언적 명세이다.

디플로이먼트 리소스를 통해 다음을 할 수 있다.

  • (레플리카셋, 즉 복제본 구성을 이용하여) 파드를 원하는 개수만큼 실행시킬 수 있다.
  • (제어판 Control Plane을 이용하여) 파드를 업데이트 할 수 있다.
  • 파드를 롤백하는 것도 가능하다.

다양한 배포 전략

애플리케이션의 여러 복제본이 존재할 경우, 이 각각의 복제본을 새 버전으로 업데이트하는 방법으로 다음과 같은 배포 전략이 있음을 배웠다.

  • 재생성 (Recreate): 이전 버전을 삭제하고 새 버전 생성
  • 블루/그린 배포: 한 번에 이전 버전에서 새 버전으로 연결을 전환
  • 롤링 배포: 이전 버전을 scale down하고, 새 버전을 scale up 하는 방식으로 단계별로 교체, 롤아웃(rollout)
  • 카나리 배포: 새 버전이 잘 작동한다고 판단되면, 이전 버전을 교체

디플로이먼트는 파드의 복제본을 자동으로 업데이트하게 해주는 명세이므로 쿠버네티스가 지원하는 배포 전략으로는 재생성과 롤링 배포 방식을 선택할 수 있다.

디플로이먼트 적용하기

위에서 만든 디플로이먼트 정의 파일을 적용하기 위해서는 다음 명령을 사용한다.

kubectl apply -f <디플로이먼트_파일>

디플로이먼트(Deployment)로 스테이트리스 애플리케이션 실행하기: 문서 실습

  • 디플로이먼트 선언 YAML 파일 작성, 리소스 생성 및 적용
  • Pod 업데이트
  • 복제본을 통한 Scale out

nginx 디플로이먼트 생성하고 탐색하기

  1. YAML 파일을 기반으로 디플로이먼트를 생성한다.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80
kubectl apply -f deployment.yaml

  1. 디플로이먼트에 대한 정보를 살펴본다.
 kubectl describe deployment nginx-deployment

출력은 다음과 유사하다.

Name:                   nginx-deployment
Namespace:              default
CreationTimestamp:      Mon, 13 Feb 2023 08:55:48 +0900
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=nginx
Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=nginx
  Containers:
   nginx:
    Image:        nginx:1.14.2
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   nginx-deployment-85996f8dbd (2/2 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  23s   deployment-controller  Scaled up replica set nginx-deployment-85996f8dbd to 2

  1. 디플로이먼트에 의해 생성된 파드를 나열한다.
kubectl get pods -l app=nginx

출력은 다음과 유사하다.

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-85996f8dbd-nzm46   1/1     Running   0          15m
nginx-deployment-85996f8dbd-thb9l   1/1     Running   0          15m
  1. 파드에 대한 정보를 살펴본다.
kubectl describe pod <pod-name>

디플로이먼트 업데이트하기

  1. 기존 YAML 파일에서 nginx 버전을 수정한 뒤, 새 YAML 파일을 적용한다.
kubectl apply -f deployment.yaml
  1. 디플로이먼트가 새 이름으로 파드를 생성하고 이전 파드를 삭제하는 것을 확인한다.
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-66f8758855-87qng   1/1     Running   0          9s
nginx-deployment-66f8758855-jmjxr   1/1     Running   0          24s

이전의 pod들은 삭제되고 새 파드 2개가 생성됐다.


레플리카 수를 늘려 애플리케이션 확장하기

  1. 기존 YAML 파일에서 replica 수를 4로 수정한 뒤, 새 YAML 파일을 적용한다.
kubectl apply -f deployment.yaml
  1. 디플로이먼트에 4개의 파드가 있는지 확인한다.
kubectl get pods -l app=nginx

출력은 다음과 유사하다.

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-85996f8dbd-22c27   1/1     Running   0          33s
nginx-deployment-85996f8dbd-jmf9b   1/1     Running   0          28s
nginx-deployment-85996f8dbd-tzcwj   1/1     Running   0          28s
nginx-deployment-85996f8dbd-wslpt   1/1     Running   0          33s

디플로이먼트 삭제하기

kubectl delete deployment nginx-deployment



서비스

파드를 외부로 노출 시키기

클러스터 안에 파드는 각각 고유의 IP를 가지고 있지만, 직접 우리가 내부망에 접속할 수 있는 것은 아니다. 그럼 어떻게 파드 안에 서비스가 외부로 노출될 수 있을까?

서비스, 로드밸런싱, 네트워킹 공식문서의 설명을 인용해보자.

  • 서비스 리소스를 사용하면 파드에서 실행 중인 애플리케이션을 클러스터 외부에서 접근할 수 있다.
  • 또한 서비스를 사용하여 클러스터 내부에서 사용할 수 있는 서비스만 게시할 수 있다.
    쿠버네티스에서 서비스는 파드의 집합에 접근할 수 있는 정책을 정의하는 추상적 개념이다.
    서비스 리소스가 정의된 YAML 파일에 selector라는 것을 이용해 서비스할 대상 타겟을 설정할 수 있다.

앞서 디플로이먼트를 통해 파드의 복제본을 원하는 개수만큼 실행시킬 수 있다고 언급했다.
서비스 리소스는 이러한 파드 집합에 접근할 수 있게 하며, 파드가 교체되거나, 어떤 특정 파드에 문제가 생긴 경우에도 사용 가능한 파드를 찾아 알아서 접속할 수 있게 돕는다.

서비스 만들어보기

다음의 서비스 리소스의 예제이다.

apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  selector:
    app: nginx # 배포하려는 파드를 지정합니다. 당연히 파드가 이미 실행중이어야 합니다.
  type: LoadBalancer
  ports:
  - name: nginx
    protocol: TCP
    port: 80
    targetPort: 80

우리에게 가장 익숙한 LoadBalancer로 서비스를 만들고, 백엔드에 cozserver라는 이름을 가진 파드 집합에 연결되도록 지정했다.
적용된 결과를 확인해자.

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl get svc
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-minikube   NodePort       10.106.160.84   <none>        8080:30951/TCP   164m
kubernetes       ClusterIP      10.96.0.1       <none>        443/TCP          170m
nginx            LoadBalancer   10.108.172.93   <pending>     80:30523/TCP     25s

minikube에서는 EXTERNAL-IP가 pending 상태로 진전이 되지 않는다
minikube tunnel 명령을 이용하면 EXTERNAL-IP가 127.0.0.1로 설정되며, 그때부터 http://localhost로 접속이 가능해진다.
접속이 원활하지 않을 경우, tunnel을 중지하고 해당 명령을 다시 시도해보자.

minikube tunnel
kubectl get svc
NAME             TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
hello-minikube   NodePort       10.106.160.84   <none>        8080:30951/TCP   168m
kubernetes       ClusterIP      10.96.0.1       <none>        443/TCP          173m
nginx            LoadBalancer   10.108.172.93   127.0.0.1     80:30523/TCP     4m10s

0개의 댓글