관리 메뉴

피터의 개발이야기

[Kubernetes] Pod 상태 문제 확인하는 방법, CrashLoopBackOff 원인분석 본문

Kubernetes/트러블슈팅&장애대응

[Kubernetes] Pod 상태 문제 확인하는 방법, CrashLoopBackOff 원인분석

기록하는 백앤드개발자 2022. 6. 27. 23:16
반응형

 

 

ㅁ 개요

 ㅇ Amazon Elastic Kubernetes Service(Amazon EKS)환경에서 Jenkins를 Pod로 생성하여 사용 중이다

 ㅇ 검수계의 경우 비용절감을 위해 일과시간만 사용하다보니 포드가 생성되는 과정에서 에러가 발생할 때가 있다.

 ㅇ 젠킨스의 error 상황을 확인하고 조치하는 과정을 정리해 보았다.

 

ㅁ 포드 상태 확인

 kubectl get pod | grep jenkins

 ㅇ CrashLoopBackOff 상태로 현재 포드는 기동되어 있지 않은 상태이다.

 ㅇ CrashLoopBackOff에 걸린 포드가 반복적으로 시작되고 충돌합니다.

 ㅇ "Back-Off restarting failed container" 출력 메시지를 수신하는 경우

     Kubernetes가 컨테이너를 시작한 직후에 컨테이너가 종료되었을 수 있다.

 ㅇ 현재 Pod의 로그에서 오류를 찾으려면 로그를 확인해야한다.

 

ㅁ 포드의 LOG 확인

kubectl logs jenkins-kubernetes-6547dbfd9-xsmcj
Error from server (BadRequest): container "jenkins-kubernetes" in pod "jenkins-kubernetes-6547dbfd9-xsmcj" is waiting to start: PodInitializing

 ㅇ container가 제대로 생성되지 않는 문제점이 발생하였다.

 

ㅁ  CrashLoopBackOff 상태에서 포드 이벤트 확인 

kubectl describe pod jenkins-kubernetes-6547dbfd9-r7jh6

Events:
  Type     Reason                  Age                    From                     Message
  ----     ------                  ----                   ----                     -------
  Warning  FailedScheduling        54m (x432 over 11h)    default-scheduler        no nodes available to schedule pods
  Warning  FailedScheduling        49m                    default-scheduler        0/1 nodes are available: 1 node(s) had taint {dedicated: rsts}, that the pod didn't tolerate.
  Normal   SuccessfulAttachVolume  48m                    attachdetach-controller  AttachVolume.Attach succeeded for volume "pvc-aaaaaaa"
  Warning  FailedCreatePodSandBox  47m                    kubelet                  Failed to create pod sandbox: rpc error: code = Unknown desc = failed to set up sandbox container "ae109fef236d4d328a8e864ff96c22b65d23e34e1e3f9767fe9be13b7b0feffa" network for pod "jenkins-kubernetes-6547dbfd9-r7jh6": networkPlugin cni failed to set up pod "jenkins-kubernetes-6547dbfd9-r7jh6_default" network: add cmd: failed to assign an IP address to container
  Normal   SandboxChanged          47m                    kubelet                  Pod sandbox changed, it will be killed and re-created.
  Normal   Pulled                  46m                    kubelet                  Successfully pulled image "jenkins/jenkins:lts" in 1m22.581886955s
  Normal   Pulled                  45m                    kubelet                  Successfully pulled image "jenkins/jenkins:lts" in 2.245270856s
  Normal   Pulled                  45m                    kubelet                  Successfully pulled image "jenkins/jenkins:lts" in 2.187960494s
  Normal   Pulled                  45m                    kubelet                  Successfully pulled image "jenkins/jenkins:lts" in 2.214754191s
  Normal   Created                 45m (x4 over 46m)      kubelet                  Created container copy-default-config
  Normal   Pulling                 44m (x5 over 47m)      kubelet                  Pulling image "jenkins/jenkins:lts"
  Normal   Started                 42m (x6 over 46m)      kubelet                  Started container copy-default-config
  Warning  BackOff                 2m46s (x196 over 45m)  kubelet                  Back-off restarting failed container

 

ㅇ 첫 이벤트는 Node의 CPU 부족으로 인해 node를 할당 받지 못하였다. ( Warning  FailedScheduling) 

ㅇ 1차 의심을 Node의 리소스 부족을 확인하였다.

 

ㅁ 쿠버네티스의 리소스 확인

$ kubectl describe deployments.apps jenkins
Containers:
   jenkins-kubernetes:
    Image:       jenkins/jenkins:lts
    Ports:       8080/TCP, 50000/TCP
    Host Ports:  0/TCP, 0/TCP
    Args:
      --argumentsRealm.passwd.$(ADMIN_USER)=$(ADMIN_PASSWORD)
      --argumentsRealm.roles.$(ADMIN_USER)=admin
    Limits:
      cpu:     1800m
      memory:  2Gi
    Requests:
      cpu:      50m
      memory:   256Mi

 ㅇ 리소스 Limits와 Requests에 근본적인 문제는 없어 보였다. CPU의 Limit가 적은 것도 아니었다.

 ㅇ Containers > Image tag가 lts, 즉 최신으로 정의 되어 있는 부분이 의심스러웠다.

 ㅇ 그래서 Image tag를 lts가 아닌 다운그레이드 버젼을 지정하기로 하였다.

 ㅇ 자세한 describe는 아래 더보기를 참조하세요.

더보기

Name:               jenkins-kubernetes
Namespace:          default
CreationTimestamp:  Mon, 23 Nov 2020 11:15:18 +0900
Labels:             app.kubernetes.io/component=jenkins-master
                    app.kubernetes.io/instance=jenkins-kubernetes
                    app.kubernetes.io/managed-by=Tiller
                    app.kubernetes.io/name=jenkins
                    helm.sh/chart=jenkins-1.3.6
Annotations:        deployment.kubernetes.io/revision: 8
Selector:           app.kubernetes.io/component=jenkins-master,app.kubernetes.io/instance=jenkins-kubernetes
Replicas:           1 desired | 1 updated | 1 total | 0 available | 1 unavailable
StrategyType:       Recreate
MinReadySeconds:    0
Pod Template:
  Labels:           app.kubernetes.io/component=jenkins-master
                    app.kubernetes.io/instance=jenkins-kubernetes
                    app.kubernetes.io/managed-by=Tiller
                    app.kubernetes.io/name=jenkins
                    helm.sh/chart=jenkins-1.3.6
  Annotations:      checksum/config: 
  Service Account:  jenkins-kubernetes
  Init Containers:
   copy-default-config:
    Image:      jenkins/jenkins:lts
    Port:       <none>
    Host Port:  <none>
    Command:
      sh
      /var/jenkins_config/apply_config.sh
    Limits:
      cpu:     1200m
      memory:  2Gi
    Requests:
      cpu:     50m
      memory:  256Mi
    Environment:
      ADMIN_PASSWORD:  <set to the key 'jenkins-admin-password' in secret 'jenkins-kubernetes'>  Optional: false
      ADMIN_USER:      <set to the key 'jenkins-admin-user' in secret 'jenkins-kubernetes'>      Optional: false
    Mounts:
      /tmp from tmp (rw)
      /usr/share/jenkins/ref/plugins from plugins (rw)
      /usr/share/jenkins/ref/secrets/ from secrets-dir (rw)
      /var/jenkins_config from jenkins-config (rw)
      /var/jenkins_home from jenkins-home (rw)
      /var/jenkins_plugins from plugin-dir (rw)
  Containers:
   jenkins-kubernetes:
    Image:       jenkins/jenkins:lts
    Ports:       8080/TCP, 50000/TCP
    Host Ports:  0/TCP, 0/TCP
    Args:
      --argumentsRealm.passwd.$(ADMIN_USER)=$(ADMIN_PASSWORD)
      --argumentsRealm.roles.$(ADMIN_USER)=admin
    Limits:
      cpu:     1800m
      memory:  2Gi
    Requests:
      cpu:      50m
      memory:   256Mi
    Liveness:   http-get http://:http/login delay=90s timeout=5s period=10s #success=1 #failure=5
    Readiness:  http-get http://:http/login delay=60s timeout=5s period=10s #success=1 #failure=3
    Environment:
      JAVA_OPTS:                 -Dorg.apache.commons.jelly.tags.fmt.timeZone=Asia/Seoul
                                 -Dorg.csanchez.jenkins.plugins.kubernetes.pipeline.ContainerExecDecorator.websocketConnectionTimeout=180
                                 
      JENKINS_OPTS:              
      JENKINS_SLAVE_AGENT_PORT:  50000
      ADMIN_PASSWORD:            <set to the key 'jenkins-admin-password' in secret 'jenkins-kubernetes'>  Optional: false
      ADMIN_USER:                <set to the key 'jenkins-admin-user' in secret 'jenkins-kubernetes'>      Optional: false
    Mounts:
      /tmp from tmp (rw)
      /usr/share/jenkins/ref/plugins/ from plugin-dir (rw)
      /usr/share/jenkins/ref/secrets/ from secrets-dir (rw)
      /var/jenkins_config from jenkins-config (ro)
      /var/jenkins_home from jenkins-home (rw)
  Volumes:
   plugins:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:     
    SizeLimit:  <unset>
   tmp:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:     
    SizeLimit:  <unset>
   jenkins-config:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      jenkins-kubernetes
    Optional:  false
   plugin-dir:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:     
    SizeLimit:  <unset>
   secrets-dir:
    Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
    Medium:     
    SizeLimit:  <unset>
   jenkins-home:
    Type:       PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  jenkins-kubernetes
    ReadOnly:   false
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Progressing    True    NewReplicaSetAvailable
  Available      False   MinimumReplicasUnavailable
OldReplicaSets:  jenkins-kubernetes-6547dbfd9 (1/1 replicas created)
NewReplicaSet:   <none>
Events:          <none>

 

 ㅇ 파드 및 컨테이너 리소스 관리에 대한 구체적인 정보는 아래의 링크를 참조하면 된다. 

 

파드 및 컨테이너 리소스 관리

파드를 지정할 때, 컨테이너에 필요한 각 리소스의 양을 선택적으로 지정할 수 있다. 지정할 가장 일반적인 리소스는 CPU와 메모리(RAM) 그리고 다른 것들이 있다. 파드에서 컨테이너에 대한 리소

kubernetes.io

 

ㅁ Jenkins Docker image version 확인

 ㅇ Docker hub의 jenkins/jenkins에서 적절한 Tag를 찾아야한다. 

 ㅇ Jenkins Tag정보 확인을 위해 DockerHub Jenkins로 이동한다.

 ㅇ 최종적으로 찾은 버젼은 2.355-jdk11이었다.

 

 ㅇ 2.2XX 버젼으로 다운 그레이드를 하여 진행하였지만, 플러그인의 호완성 문제가 발견되어 2.355까지 올리는 과정을 거치게 되었다.

 

ㅁ Kubenetes pod resource edit

kubectl edit deploy jenkins-kubernetes

spec:
      containers:
        image: jenkins/jenkins:2.355-jdk11
        imagePullPolicy: Always

 ㅇ image tag를  lts -> 2.355-jdk11로 수정한다.

 

 ㅇ 실제 편집 작업 시의 모습이다.

 

ㅁ 젠킨스 정상작동 확인

ㅁ 함께 보면 좋은 사이트

 ㅇ Kubernetes - 장애 발생 시 진단 Process 정의

 ㅇ 도커허브 Image version 확인 

반응형
Comments