본문 바로가기
네트워크/k8s

[k8s] 20. Pod - ReadinessProbe, LivenessProbe - 실습

by Lauren X Ming 2021. 2. 17.

Pod - ReadinessProbe, LivenessProbe

image

1. ReadinessProbe

image

  • 이 구성을 만들고, 외부에서 이 서비스에 계속 트래픽을 날릴 것

Service

apiVersion: v1
kind: Service
metadata:
  name: svc-readiness
spec:
  selector:
    app: readiness
  ports:
  - port: 8080
    targetPort: 8080

Pod

apiVersion: v1
kind: Pod
metadata:
  name: pod1
  labels:
    app: readiness  
spec:
  containers:
  - name: container
    image: kubetm/app
    ports:
    - containerPort: 8080    
  terminationGracePeriodSeconds: 0

Pod2

apiVersion: v1
kind: Pod
metadata:
  name: pod-readiness-exec1
  labels:
    app: readiness  
spec:
  containers:
  - name: readiness
    image: kubetm/app
    ports:
    - containerPort: 8080    
    readinessProbe:
      exec:
        command: ["cat", "/readiness/ready.txt"]
      initialDelaySeconds: 5
      periodSeconds: 10
      successThreshold: 3
    volumeMounts:
    - name: host-path
      mountPath: /readiness
  volumes:
  - name : host-path
    hostPath:
      path: /tmp/readiness
      type: DirectoryOrCreate
  terminationGracePeriodSeconds: 0
  • Volume으로 연결할건데, ready.txt가 없어서 계속 Ready: false 예정
  • 컨테이너 안에 readinessProbe가 있음

실습 과정

  1. 서비스 만들기

  2. Pod 만들기

  3. 서비스의 Cluster IP 복사하고 마스터노드에서 다음 명령어 입력

    while true; do date && curl 10.108.83.67:8080/hostname; sleep 1; done

    image

  4. Pod2 생성
    Pod2를 만들어도 Pod2로 트래픽이 흐르지 않음

  5. 이벤트 확인

    kubectl get events -w | grep pod-readiness-exec1

    image

  6. Probe 상태 확인

    kubectl describe pod pod-readiness-exec1 | grep -A5 Conditions

    -A, --after-context=NUM print NUM lines of trailing context
    image
    Ready, ContainerReady가 flase

  7. 앤드포인트 확인

     kubectl describe endpoints svc-readiness

    image
    NotReadyAddresses에 Pod2의 ip
    Addresses로 나온 ip는 Pod의 주소

  8. Pod2의 노드 위치 확인 후 해당 노드에서 ready.txt 파일 만들기
    image
    노드1에 있음

    cd /tmp/readiness
    touch ready.txt

    image
    image
    정상적으로 트래픽이 흐름
    Ready, ContainerReady true
    NotReadyAddresses가 없어짐

2. LivenessProbe

image

  • 서비스에 파드가 연결되고, LivenessProbe가 달려있는 파드를 만들어서 running
  • 파드의 앱 내용은 /health를 날리면 Status:200을 줌
  • 쿠버네티스가 5초 딜레이 후 10초마다 LivenessProbe를 확인

Service

apiVersion: v1
kind: Service
metadata:
  name: svc-liveness
spec:
  selector:
    app: liveness
  ports:
  - port: 8080
    targetPort: 8080

Pod

apiVersion: v1
kind: Pod
metadata:
  name: pod2
  labels:
    app: liveness
spec:
  containers:
  - name: container
    image: kubetm/app
    ports:
    - containerPort: 8080
  terminationGracePeriodSeconds: 0

Pod2

apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-httpget1
  labels:
    app: liveness
spec:
  containers:
  - name: liveness
    image: kubetm/app
    ports:
    - containerPort: 8080
    livenessProbe:
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
      failureThreshold: 3
  terminationGracePeriodSeconds: 0
  • httpGet으로 /health와 port: 8080 확인
  • 그 밑에 옵션들 달려있음

실습 과정

  1. Service 생성

  2. Pod 생성

  3. Pod2 생성

  4. Service cluster IP로 다음 명령어 실행

    while true; do date && curl 10.101.54.250:8080/health; sleep 1; done

    image
    Pod, Pod2 둘 다 트래픽이 잘 감

  5. 파드의 이벤트 확인

    watch "kubectl describe pod pod-liveness-httpget1 | grep -A10 Events"

    image

    이미지가 pull 됨
    컨테이너가 만들어지고 있음
    컨테이너가 시작이 됐음

  6. 앱을 500 리턴하도록 명령어 실행, ip는 Pod2의 ip

    curl 20.111.156.116:8080/status500

    image
    image
    이벤트에서 실패했다고 3번뜨면, 파드가 Killing이 되고 파드가 다시 Created 후 Started

Event 조회 명령어

kubectl get events -w | grep pod-readiness-exec1
  • Object들의 모든 Event 정보를 지속적으로 조회해서 | 그중에 pod-readiness-exec1라는 단어와 매칭되는 내용만 출력
watch "kubectl describe pod pod-readiness-exec1 | grep -A20 Events"
  • pod-readiness-exec1이름의 Pod 상세 내용중에 | Events와 매칭되는 단어에서 20번째 줄까지 지속적으로 출력

출처

인프런 - 대세는 쿠버네티스

아니 근데
  curl 20.111.156.116:8080/status500

이거한다고 Status Code가 달라지나?
애초에 무슨 앱이길래?
YAML에 아무 내용도 없는데?

내용이 없기는

  spec:
    containers:
    - name: liveness
      image: kubetm/app

image

도커를 모르니 이런 헛소리를 하는구나 ㅋ_ㅋ
도커 pull해보고 내용 확인하기

  docker pull kubetm/app
  docker run -ti kubetm/app /bin/bash
  ls
  app.js  bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

app.js

  var http = require('http');
  var url = require('url');
  var os = require('os');
  var fs = require('fs');
  var util = require('util');
  var log_app = fs.createWriteStream('/app.log', {flags: 'w'});
  var log_ter = fs.createWriteStream('/dev/termination-log', {flags : 'w'});
  var log_stdout = process.stdout;
  var status = 200;

  function sleep (time) {
    return new Promise((resolve) => setTimeout(resolve, time));
  }

  var content = function(req, resp) {
   var path = url.parse(req.url).pathname;
   resp.writeHead(status);
   var stdlog = "Time: " + Date(Date.now()).toLocaleString() + ", Response Path : " + path;
   log_stdout.write(util.format(stdlog) + '\n');
   log_app.write(util.format(stdlog) + '\n');

   if (path.includes('favicon')){
     resp.writeHead(200);
     resp.end();

   } else if (path.includes('hostname')){
     resp.end("Hostname : "+os.hostname() + "\n");

   } else if (path.includes('version')){
     resp.end("Version : v1" + "\n");

   } else if (path.includes('ingress1') || path.includes('ingress2')){
     resp.end("Hostname : "+os.hostname() + "\n");

   } else if (path.includes('health')){
     if (status == 500){
       resp.end(os.hostname() + " : Internal Server Error" + "\n");
     } else {
       resp.end(os.hostname() + " is Running" + "\n");
     }

   } else if (path.includes('status')){
     if (path.includes('500')){
       status = 500;
       resp.end("Status Code has Changed to 500" + "\n");
     } else {
       status = 200;
       resp.end("Status Code has Changed to 200" + "\n");
     }

   } else if (path.includes('sleep')){
     if (path.includes('30')){
        sleep(30000).then(() => {resp.end("Sleep 30" + "\n");});
     } else if (path.includes('100')){
        sleep(100000).then(() => {resp.end("Sleep 100" + "\n");});
     }

   } else if (path.includes('termination')){
     try {
       throw new Error('User called process.exit()');
     } catch (e) {
       log_ter.write(e.message);
       process.exit();
     }

   } else {
     resp.end("No defined Path." + "\n");
   }
  }
  var w = http.createServer(content);
  w.listen(8080);
  • app.js가 따박따박 리턴해준 것

'네트워크 > k8s' 카테고리의 다른 글

[k8s] 22. Pod - Node Scheduling  (0) 2021.02.17
[k8s] 21. Pod - QoS Classes  (0) 2021.02.17
[k8s] 19. Pod - ReadinessProbe, LivenessProbe  (0) 2021.02.17
[k8s] 18. Pod - Lifecycle  (0) 2021.02.16
[k8s] 17. DaemonSet, Job, CronJob - 실습  (0) 2021.02.14