전공영역 공부 기록

쿠버네티스 pod생성 과정 디버깅

악분 2023. 1. 29. 21:26
반응형

영상: https://youtu.be/ijdO1NwB2cQ

 

시작하며

쿠버네티스 pod가 어떻게 생성되는지 궁금해서 로그를 분석했습니다. 그리고 쿠버네티스 공식문서를 읽고 컨셉에 대해 이해하려고 했습니다.

 

pod생성과정.pdf
1.26MB
create_pod.log
0.03MB
create_deployment.log
0.11MB

 

선수지식

이 글을 이해하기 위해 쿠버네티스 component들이 무엇이 있는지 알아야 합니다. pod를 생성하기 위해 많은 쿠버네티스 component들이 생성과정에 참여하기 때문입니다.

링크:
https://kubernetes.io/docs/concepts/overview/components/

 

공식문서에 소개된 것처럼 component는 control-plane과 worker로 분류됩니다.

 

control-plane component는 kube-system namespace에 실행됩니다. control-plane이라는 라벨이 설정되어 있기 때문에 라벨 필터링이 가능합니다.

kubectl -n kube-system get po -l tier=control-plane

 

component pod로그 분석

pod 생성과정을 분석하기 위해 시도했던 방법은 control-plane pod log로 접근했습니다. compoent가 pod로 생성되기 때문에 pod로그에 단서가 나오지 않을까 생각했습니다.

 

테스트에 사용할 pod정의는 아래와 같습니다.

apiVersion: v1
kind: Pod
metadata:
  name: example-1
  labels:
    name: example-1
spec:
  containers:
  - name: main
    image: nginx
    resources:
      limits:
        memory: "64Mi"
        cpu: "100m"
    ports:
      - containerPort: 80

 

pod를 생성하기 전 kubectl log를 tail로 모니터링했습니다. example-1만 보기 위해서 grep으로 필터링 했습니다.

kubectl -n kube-system logs -f -l tier=control-plane | grep example-1

 

kubectl create로 pod를 생성했습니다.

kubectl create -f pod.yaml

 

pod를 생성했지만 log1줄도 없었습니다!!!

 

log level수정

공식문서를 살펴보니 component log level이 낮아서 안나온 것 같더라구요. 그래서 공식문서를 참고하여 log level을 수정했습니다.

참고자료:
https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/
참고자료:
https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md

 

log level를 수정하려면 control-plane node에서 static pod manifest를 수정해야 합니다.

vi /etc/kubernetes/manifests/kube-apiserver.yaml
vi /etc/kubernetes/manifests/kube-controller-manager.yaml
vi /etc/kubernetes/manifests/kube-scheduler.yaml

 

etcd는 환경변수로 log level를 설정해야 합니다.

참고자료:
https://etcd.io/docs/v3.4/op-guide/configuration/#--log-level
env:
- name: ETCD_LOG_LEVEL
  value: "debug"

 

control-plane component log level를 수정한 후, pod가 정상적으로 실행되는지 확인합니다.

kubectl -n kube-system get po -l tier=control-plane

 

다시 pod생성 후, log분석

다시 pod를 생성해보고 log를 확인해보니, 이전에 안보였던 log가 보입니다.

 

로그를 분석하면 api-server가 생성 요청을 etcd에 기록하는 것부터 시작합니다.그리고 unscheduled pod event를 발생시킵니다.

 

그림으로 정리하면 아래와 같습니다.

 

scheduler는 unscheduled pod event를 감지하면 스케쥴링을 시작합니다. 스케쥴링은 알고리즘에 의해 pod를 실행할 node를 찾습니다. 아래 예제는 k8s-w1 node가 선정되었네요.node가 선정되면 api-server에게 스케쥴링 정보를 전달합니다. 그리고 api-server는 받은 정보를 etcd에 기록합니다.

 

이 후 과정은 api-server와 kubelet과정이어서 분석을 생략했습니다. kubelet까지 분석을 원하시면 kubelet로그를 수집하시면 됩니다.

 

deployment생성 후, controller-manager로그 분석

pod log분석을 정리하면 신기하게도 controller-manager log는 안보였습니다. 단순히 pod만 생성하면 controller가 개입하지 않아도 되기 때문입니다.

 

그래서, controller-manager로그를 보기 위해서 deployment를 생성해봤습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example-2
spec:
  selector:
    matchLabels:
      app: example-2
  template:
    metadata:
      labels:
        app: example-2
    spec:
      containers:
      - name: main
        image: nginx
        resources:
          limits:
            cpu: "100m"
            memory: "64Mi"
        ports:
        - containerPort: 80

 

kubectl create로 deployment를 생성했습니다.

kubectl create -f deployment.yaml

 

controller log가 보입니다. pod만 생성했을 때 log와 다른 점은 api-server가 사용자 요청을 etcd에 기록하면서 deployment controller도 같이 동작을 수행합니다. 아직 코드를 보지 않았지만 deployment event를 감지하여 동작하는 것으로 추측합니다.

 

deployment controller은 replica set을 생성합니다. replica set은 scale up을 진행하고 api-server에게 작업상황을 전달합니다. api-server은 받은 정보를 etcd에 기록합니다.

 

이처럼 deployment controller 상태가 변경 될 때마다 api-server에게 공유하고, api-server는 etcd에 계속 기록합니다. controller 작업이 끝나면 unscheduled pod가 발생하고 scheduler가 스케쥴링을 시작합니다.

 

결론

log를 분석해보니 얻은 결론은 2개였습니다.

  1. log level를 수정해야 control-plane component 많은 활동을 볼 수 있다. 하지만 운영단계에서 적용하면 스토리지 용량관리가 안되므로 테스트에서만 사용해야할 것 같다.
  2. api-server만 etcd에 접근한다.

 

부록

kubectl event로 pod생성과정을 간략하게 유추할 수 있습니다.

kubectl get event --sort-by=.metadata.creationTimestamp

 

kubectl event는 namespace의 모든 event가 보이므로 kubectl describe pod로 특정 pod event만 필터링 할 수 있습니다.

kubectl describe pod {pod이름}

 

반응형