Kubernetes Workloads


Kubernetes Workloads

Workloads는 쿠버네티스에서 구동되는 어플리케이션이다. 워크로드는 Pod에서 실행한다. Pod는 Kubernetes cluster에서 실행 중인 컨테이너 집합을 나타낸다.

Kubernetes는 다음과 같이 여러 build-in 워크로드 리소스를 제공한다.

  • Deployment and ReplicaSet
    Deployment는 stateless application workload를 관리하기에 적합하다.

  • StatefulSet
    State를 추적하는 하나 이상의 파드를 동작하게 해준다. 만약 workload가 데이터를 기록하는 경우 StatefulSet을 실행하는게 적합하다.

  • DaemonSet
    DaemonSet은 노드-로컬 기능을 제공하는 Pods를 정의한다.

  • Job and CronJob
    Job과 CronJob은 실행 완료 후 중단되는 작업을 정의한다.

1. Pods

Pods는 kubernetes에서 가장 작은 배포가능한 단위이며 컨테이너의 그룹이다. 이 그룹은 스토리지 및 네트워크를 공유하고 컨테이너를 구동하는 방식에 대한 specification을 갖는다.

Pods in a Kubernetes cluster are used in two main ways:

  • Pods that run a single container.
  • Pods that run multiple containers that need to work together.
    • 하나의 Pods에서 multiple containers를 실행하는 경우는 각 컨테이너가 tight하게 결합되어 리소스를 공유해야 하는 경우 사용하며 co-located containers들은 single cohesive unit of service를 형성한다.

2. Pods Lifecycle

Pods는 Pending 단계에서 시작해서, Primary container 중 적어도 하나가 OK로 시작하면 Running 단계를 통과하고, 그런 다음 컨테이너가 실패로 종료되었는지 여부에 따라 Succeeded 또는 Failed 단계로 이동한다.

파드가 실행되는 동안, kubelet은 일종의 오류를 처리하기 위해 컨테이너를 다시 시작할 수 있다. 파드 내에서, 쿠버네티스는 다양한 컨테이너 상태를 추적하고 파드를 다시 정상 상태로 만들기 위해 취할 조치를 결정한다.
쿠버네티스 API에서 파드는 명세와 실제 상태를 모두 가진다. Pods 오브젝트의 status는 Pods 컨디션으로 구성된다. 사용자의 애플리케이션에 유용한 경우, 파드의 컨디션 데이터에 사용자 정의 Pod readiness를 삽입할 수도 있다. Pod readiness 참고
파드는 파드의 수명 중 한 번만 스케줄된다. 파드가 노드에 스케줄(할당)되면, 파드는 중지되거나 종료될 때까지 해당 노드에서 실행된다.

sample describe nginx

Containers:
  nginx:
    Container ID:   containerd://3106dfa5b7c804a2594e46bc8a63a9818c755e0a3125a07854dee5feda161142
    Image:          nginx
    Image ID:       docker.io/library/nginx@sha256:aa0afebbb3cfa473099a62c4b32e9b3fb73ed23f2a75a65ce1d4b4f55a5c2ef2
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Mon, 13 Mar 2023 09:34:11 +0900
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-4fr4z (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True

Pod Phase

Phase는 파드의 라이프사이클 단계를 간단하게 요약 하여 표현한다.

                        +-----> Succeeded  
                        |  
> Pending --> Running ->|  
                        |  
                        +-----> Failed  

> Unknown 
  • Pending: Accepted by kubernetes cluster, but one or more of the containers has not been set up and made ready to run. This includes time a Pod spends waiting to be scheduled and the time spent downloading container images.
  • Running: The Pod has been bound to a node. All of the containers have been created. At least one container is still running, or is in the process of starting or restarting.
  • Succeeded: All containers in the Pod have terminated in success, and will not be restarted.
  • Failed: All containers in the Pod have terminated and at least one container has terminated in failure.
  • Unknown: For some reason the state of the Pod could not be obtained. This phase typically occurs due to an error in communicating with the node where the Pod should be running.

쿠버네티스는 노드의 통신이 끊기거나 다운되면 해당 노드의 모든 파드 상태를 Failed로 처리하는 정책을 적용한다.

Container States

Kubernetes는 Pod의 Phase 뿐만아니라 파드 내부 각 Container의 상태도 추적한다. Container Lifecycle hook을 이용하면 특정 지점에서 실행할 이벤트를 트리거도 가능하다. 스케줄러가 파드를 노드에 할당하면, kubelet은 container runtime을 사용해 Pod의 container를 생성한다. 이 때 container의 상태는 아래와 같이 3개의 상태이다.

  • Waiting: Running, Terminated 상태가 아니면 Waiting 상태다. 이 상태는 컨테이너 시작이 완료되는데 필요한 작업을 진행한다. (Pulling image, Applying secret data 등)
  • Running: Container가 문제 없이 실행되고 있는 단계.
  • Terminated:
Container lifecycle hook test

nginx-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
      preStop:
        exec:
          command:
          - "sh"
          - "-c"
          - >
            curl localhost;
            sleep 15;
            curl localhost;
$ k apply -f nginx-pod.yaml

$ k delete -f nginx-pod.yaml

$ k logs -f nginx
.......
2023/04/04 03:00:22 [notice] 1#1: using the "epoll" event method
2023/04/04 03:00:22 [notice] 1#1: nginx/1.23.4
2023/04/04 03:00:22 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
2023/04/04 03:00:22 [notice] 1#1: OS: Linux 5.10.167-147.601.amzn2.x86_64
2023/04/04 03:00:22 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2023/04/04 03:00:22 [notice] 1#1: start worker processes
2023/04/04 03:00:22 [notice] 1#1: start worker process 35
2023/04/04 03:00:22 [notice] 1#1: start worker process 36

# Immediately called  > curl localhost
::1 - - [04/Apr/2023:06:58:06 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.74.0" "-"
# Waiting 15 Sec 
# and called > curl localhost
::1 - - [04/Apr/2023:06:58:21 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.74.0" "-"

# Pod got signal
2023/04/04 06:58:21 [notice] 1#1: signal 3 (SIGQUIT) received, shutting down
2023/04/04 06:58:21 [notice] 36#36: gracefully shutting down
2023/04/04 06:58:21 [notice] 36#36: exiting
2023/04/04 06:58:21 [notice] 36#36: exit
2023/04/04 06:58:21 [notice] 35#35: gracefully shutting down
2023/04/04 06:58:21 [notice] 35#35: exiting
2023/04/04 06:58:21 [notice] 35#35: exit
2023/04/04 06:58:21 [notice] 1#1: signal 17 (SIGCHLD) received from 36
2023/04/04 06:58:21 [notice] 1#1: worker process 35 exited with code 0
2023/04/04 06:58:21 [notice] 1#1: worker process 36 exited with code 0
2023/04/04 06:58:21 [notice] 1#1: exit

여기서 sleep을 20초로 변경하면 curl 수행 시간의 차이는 20초로 변경된다. Pod는 종료 전 preStop 훅을 실행한다. 만약 preStop 훅이 terminationGracePeriodSeconds의 Default 값인 30초 내에 수행 되지 않는다면 Container는 강제 종료된다.
따라서 sleep의 시간을 40초로 변경하여도 terminationGracePeriodSeconds 시간 30초가 지나면 강제 종료된다.

2023/04/04 07:03:24 [notice] 1#1: start worker process 36
2023/04/04 07:03:24 [notice] 1#1: start worker process 37
::1 - - [04/Apr/2023:07:03:28 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.74.0" "-"
2023/04/04 07:03:58 [notice] 1#1: signal 3 (SIGQUIT) received, shutting down
2023/04/04 07:03:58 [notice] 36#36: gracefully shutting down
2023/04/04 07:03:58 [notice] 36#36: exiting
2023/04/04 07:03:58 [notice] 36#36: exit
2023/04/04 07:03:58 [notice] 37#37: gracefully shutting down
2023/04/04 07:03:58 [notice] 37#37: exiting
2023/04/04 07:03:58 [notice] 37#37: exit
2023/04/04 07:03:58 [notice] 1#1: signal 17 (SIGCHLD) received from 37
2023/04/04 07:03:58 [notice] 1#1: worker process 36 exited with code 0
2023/04/04 07:03:58 [notice] 1#1: worker process 37 exited with code 0
2023/04/04 07:03:58 [notice] 1#1: exit

sleep을 40초로 걸었을 때 로그를 확인해보면 마지막 curl localhost가 호출되지 않았음을 알 수 있다. preStop 훅이 완전히 종료되기 전에 terminationGracePeriodSeconds 시간에 의해 Container가 강제 종료되는 것을 확인할 수 있다.

3. Pod Lifetime




  • References [1] https://kubernetes.io/docs/concepts/workloads/
    [2] https://learnk8s.io/graceful-shutdown

Tag: [ incubator  ]