[K8s]4. pod 배포관리

[K8s]4. pod 배포관리


이 글은 쿠버네티스 인 액션 이라는 책과 검색을 통해서 공부한 것을 정리합니다.

포드 배포 관리

포드를 안정적으로 유지하기

주 프로세스에 크래시가 발생하면 Kubelet이 컨테이너를 다시 시작하게 함
반두시 프로세스의 크래시 이외에도, 메모리 누수로 OOM이 발생하는 경우가 발생 할 수 있다.
그러면 현재 애플리케이션의 상태를 외부에서 체크하는 방법에 대해서 알아본다.

라이브니스 프로브(liveness Probe)

컨테이너가 살아이는지 확인하는 주된 방법

  • (1) HTTP GET 프로브
    • 지정한 IP 주소, 포트, 경로에 HTTP GET 요청을 수행한다.
    • 서버가 오류 응답코드를 리턴하거나 응답하지 않으면 프로브는 실패로 간주하고 컨테이너를 다시 시작함.
  • (2) TCP 소켓 프로브
    • 컨테이너의 지정된 포트에 TCP를 연결하려고 시도한다.
    • 성공적으로 연결이되지 않으면 컨테이너가 다시 시작된다.
  • (2) Exec 프로브
    • 컨테이너 내부에 임의의 명령을 실행하고, 명령의 종료 상태 코드를 확인한다.
    • 상태 코드가 0이면 검사 성공. 다른 코드는 오류로 간주한다.

실습

  • kubia-liveness-probe.yml 작성 및 생성(create)
  1 apiVersion: v1
  2 kind: Pod
  3 metadata:
  4   name: kubia-liveness
  5 spec:
  6   containers:
  7   - image: luksa/kubia-unhealthy # 문제가 있는 애플리케이션을 포함하는 이미지임.
  8     name: kubia
  9     livenessProbe: # Http Get을 수행할 라이브니스 프로브
 10       httpGet:
 11         path: /  # 네트워크 포트 HTTP 요청에서 요청할 경로
 12         port: 8080  # 프로브가 연결해야 하는 네트워크 포트
  • 동작 중인 liveness probe 확인(시간이 조금 지난 후에)
  • $ kubectl get po kubia-liveness
NAME             READY   STATUS    RESTARTS   AGE
kubia-liveness   1/1     Running   15         61m
  • $ kubectl describe po kubia-liveness
(생략)

Exit Code:    137

(생략)

  Normal   Scheduled  <unknown>              default-scheduler  Successfully assigned default/kubia-liveness to minikube
(생략)
  Warning  Unhealthy  8s (x49 over 62m)      kubelet, minikube  Liveness probe failed: HTTP probe failed with statuscode: 500
  • Exit Code: 137 : 128 + x 즉 kill 신호인 9로 프로세스가 강제 종료
  • warning이 쭉 나열된다.

결론

컨테이너가 강제 종료되면 완전히 새로운 컨테이너가 생성된다. 컨테이너가 재시작되는 것은 아니다.

효과적인 라이브니스 프로브 생성

운영 환경에서 실행 중인 포드의 경우, 항상 라이브니스 프로브를 정의해야 한다. 정의되지 않으면 쿠버네티스는 프로세스가 실행되는 동안 컨테이너가 정상이라고 생각한다.

라이브니스 프로브 tip

  • (1) initialDelaySeconds: x 초 는 반드시 설정.
livenessProbe:
  httpGet:
    path:/
    port: 8080
  initialDelaySeconds: 15 # 첫 번째 프로브 실행 전 15초 지전
  • (2) Exec 프로브 대신 HTTP GET을 사용하자(자바 애플리케이션의 경우)
    • 이해는 잘 안되지만? 컨테이너에서 자바 애플리케이션을 실행하는 경우에 Exec를 사용하면 liveness 정보를 얻기 위해 완전히 새로운 JVM을 가동한다. 시작 절차에 많은 리소스가 필요한 JVM 기반 애플리케이션의 경우도 마찬가지…

라이브니스 프로브 정리

쿠버네티스는 크래시가 발생하거나 라이브니스 프로브가 실패한 경우 컨테이너를 다시 시작해 컨테이너를 계속 실행한다.
위 작업은 포드를 호스팅하는 노드에서 Kubelet에 의해 수행된다.
노드 자체에 크래시가 발생하는 경우, 포드의 대체 폼을 생성해야 하는 것은 컨트롤 플레인이 한다.

리플리케이션 컨트롤러

  • deprecated
  • ReplicaSet을 구성하는 Deployment 가 권장됨.

데몬셋 (p184)

  • 데몬 셋은 클러스터의 특정 위치(노드) 에 배포된 특정 개수 의 포드를 실행하는 데 사용된다.
  • 기본적으로 특정 노드(nodeSelector 같은)를 지정하지 않으면, 데몬셋은 기본적으로 클러스터의 모든 노드에 포드를 배포함.
  • 노드가 하나 추가되었을 때, 설정된 nodeSelector나 기본값에 의해서

데몬셋 실습

  • ssd-monitor-deamonset.yml
    Liveness:       http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:    <none>
    Mounts:
  1 apiVersion: apps/v1 #데몬셋은 apiVersion이 apps/v1
  2 kind: DaemonSet
  3 metadata:
  4   name: ssd-monitor
  5 spec:
  6   selector:
  7     matchLabels:
  8       app: ssd-monitor
  9   template:
 10     metadata:
 11       labels:
 12         app: ssd-monitor
 13     spec:
 14       nodeSelector:
 15         disk: ssd
 16       containers:
 17       - name: main
 18         image: luksa/ssd-monitor

위 설정으로 먼저 실행 = nodeSelector 미설정

  • $ kubectl create -f ssd-monitor-deamonset.yml
  • $ kubectl get ds : 생성된 데몬셋을 확인
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
ssd-monitor   0         0         0       0            0           disk=ssd        56s
  • $ kubectl get po No resources found in default namespace.

node에 라벨 지정하고 살펴보기

  • $ kubectl get node
NAME       STATUS   ROLES    AGE     VERSION
minikube   Ready    master   4h15m   v1.16.0
  • $ kubectl label node minikube disk=ssd
    node/minikube labeled

  • $ kubectl get po : 확인하니 잘 올라오고 있다.

NAME                READY   STATUS    RESTARTS   AGE
ssd-monitor-fd9vq   1/1     Running   0          11s

node에서 라벨을 제거한다면?

  • 포드가 Terminating 되고 있다!!
➜ kubectl label node minikube disk=hdd --overwrite
node/minikube labeled

➜ kubectl get po
NAME                READY   STATUS        RESTARTS   AGE
ssd-monitor-fd9vq   1/1     Terminating   0          2m25s

데몬셋 추가

  • 데몬셋 자체를 삭제하면 모든 떠있는 모든 포드가 역시 삭제된다!

잡(Job), 단일 태스크를 수행하는 포드

쿠버네티스에는 Job(kind: Job) 이라는 리소스가 존재한다.
주로 특정 작업이 종료되면 Pod를 종료시킨다고 보면된다.
예를 들어서. 특정 잡을 수행하는 컨테이너가 있고, 해당 잡이 실행이 완료되면 컨테이너를 종료하는 이미지가 있다. 그렇다면 아래와 같이 yml을 정의 할 수 있다. (p190)

 1 apiVersion: batch/v1
 2 kind: Job # Job 리소스임을 명시
 3 metadata:
 4   name: batch-job
 5 spec:		# 포드 셀렉처를 지정하지 않아서, 포드 템플릿의 라벨을 기반으로 만들어짐.
 6   template:
 7     metadata:
 8       labels:
 9         app: batch-job
10     spec:
11       restartPolicy: OnFailure #or Never # 잡은 기본 재시작 정책을 사용불가. 완료시 컨테이너 재시작 불가.
12       containers:
13       - name: main
14         image: luksa/batch-job

잡에서 다수의 포드 인스턴스 실행(p192)

  (생략)
spec:
  completions: 5 # 이 잡이 다섯 개의 포드를 순차적으로 실행함.
  parallelism: 2 # 최대 2개의 포드를 병렬로 실행할 수 있음.
  (생략)

크론잡(CronJob)

  • 기본 Job의 셋팅과 큰 차이는 없으며, 아래처럼 schedule를 주면된다.
apiVersion: batch/v1beta1
kind: CronJob # 리소스명 CronJob
metadata:
  name: batch-job-every-fifteen-minutes
spec:
  schedule: "*/1  *  *  *  *" # CronJob의 핵심
  startingDeadlineSeconds: 15 # 추가 옵션. 포드는 스케줄된 시간 이후로 15초 안에 시작해야 함.
  jobTemplate:
    spec:
      template:
        metadata:
          lavels:
            app: periodic-batch-job
          spec:
            restartPolicy: OnFailure # 역시나 필요한 설정
            containers:
              - name: main
                image: luksa/batch-job
  • startingDeadlineSeconds 이 옵션은 1분(스케줄 주기) 15초 까지 시작하지 않으면 작업이 실행되지 않고 해당 잡 실행은 실패로 간주됨.