This the multi-page printable view of this section. Click here to print.
모니터링, 로깅, 그리고 디버깅
1 - 리소스 메트릭 파이프라인
컨테이너 CPU 및 메모리 사용량과 같은 리소스 사용량 메트릭은
쿠버네티스의 메트릭 API를 통해 사용할 수 있다. 이 메트릭은
kubectl top
커맨드 사용하여 사용자가 직접적으로 액세스하거나,
Horizontal Pod Autoscaler 같은 클러스터의 컨트롤러에서 결정을 내릴 때 사용될 수 있다.
메트릭 API
메트릭 API를 통해, 주어진 노드나 파드에서 현재 사용중인 리소스의 양을 알 수 있다. 이 API는 메트릭 값을 저장하지 않으므로, 예를 들어, 지정된 노드에서 10분 전에 사용된 리소스의 양을 가져오는 것과 같은 일을 할 수는 없다.
이 API와 다른 API는 차이가 없다.
- 다른 쿠버네티스 API의 엔드포인트와 같이
/apis/metrics.k8s.io/
하위 경로에서 발견될 수 있다 - 동일한 보안, 확장성 및 신뢰성 보장을 제공한다
k8s.io/metrics 리포지터리에서 이 API를 정의하고 있다. 여기에서 이 API에 대한 더 상세한 정보를 찾을 수 있다.
참고: 이 API를 사용하려면 메트릭 서버를 클러스터에 배포해야 한다. 그렇지 않으면 사용할 수 없다.
리소스 사용량 측정
CPU
CPU는 일정 기간 동안 CPU 코어에서 평균 사용량으로 리포트된다. 이 값은 커널(리눅스와 윈도우 커널 모두)에서 제공하는 누적 CPU 카운터보다 높은 비율을 적용해서 얻는다. kubelet은 비율 계산에 사용할 윈도우를 선택한다.
메모리
메모리는 메트릭이 수집된 순간 작업 집합으로 리포트 된다. 이상적인 환경에서 "작업 집합(working set)"은 압박(memory pressure)에서 풀려날 수 없는 사용 중인(in-use) 메모리의 양이다. 그러나 작업 집합의 계산은 호스트 OS에 따라 다르며, 일반적으로 휴리스틱스를 사용해서 평가한다. 쿠버네티스는 스왑(swap)을 지원하지 않기 때문에 모든 익명(파일로 백업되지 않은) 메모리를 포함한다. 호스트 OS가 항상 이러한 페이지를 회수할 수 없기 때문에 메트릭에는 일반적으로 일부 캐시된(파일 백업) 메모리도 포함된다.
메트릭 서버
메트릭 서버는 클러스터 전역에서 리소스 사용량 데이터를 집계한다.
kube-up.sh
스크립트에 의해 생성된 클러스터에는 기본적으로 메트릭 서버가
디플로이먼트 오브젝트로 배포된다. 만약 다른 쿠버네티스 설치 메커니즘을 사용한다면, 제공된
디플로이먼트 components.yaml 파일을 사용하여 메트릭 서버를 배포할 수 있다.
메트릭 서버는 각 노드에서 Kubelet에 의해 노출된 Summary API에서 메트릭을 수집하고, 쿠버네티스 aggregator를 통해 메인 API 서버에 등록된다.
설계 문서에서 메트릭 서버에 대해 자세하게 배울 수 있다.
2 - 리소스 모니터링 도구
애플리케이션을 스케일하여 신뢰할 수 있는 서비스를 제공하려면, 애플리케이션이 배포되었을 때 애플리케이션이 어떻게 동작하는지를 이해해야 한다. 컨테이너, 파드, 서비스, 그리고 전체 클러스터의 특성을 검사하여 쿠버네티스 클러스터 내의 애플리케이션 성능을 검사할 수 있다. 쿠버네티스는 각 레벨에서 애플리케이션의 리소스 사용량에 대한 상세 정보를 제공한다. 이 정보는 애플리케이션의 성능을 평가하고 병목 현상을 제거하여 전체 성능을 향상할 수 있게 해준다.
쿠버네티스에서 애플리케이션 모니터링은 단일 모니터링 솔루션에 의존하지 않는다. 신규 클러스터에서는, 리소스 메트릭 또는 완전한 메트릭 파이프라인으로 모니터링 통계를 수집할 수 있다.
리소스 메트릭 파이프라인
리소스 메트릭 파이프라인은
Horizontal Pod Autoscaler
컨트롤러와 같은 클러스터 구성요소나
kubectl top
유틸리티에 관련되어 있는
메트릭들로 제한된 집합을 제공한다. 이 메트릭은 경량의 단기 인메모리 저장소인
metrics-server에
의해서 수집되며 metrics.k8s.io
API를 통해 노출된다.
metrics-server는 클러스터 상의 모든 노드를 발견하고 각 노드의
Kubelet에 CPU와 메모리
사용량을 질의한다. Kubelet은 쿠버네티스 마스터와 노드 간의 다리 역할을 해서
머신에서 구동되는 파드와 컨테이너를 관리한다. Kubelet은 각각의 파드를 해당하는
컨테이너로 변환하고 컨테이너 런타임 인터페이스를 통해서 컨테이너 런타임에서
개별 컨테이너의 사용량 통계를 가져온다. Kubelet은 이 정보를 레거시 도커와의
통합을 위해 kubelet에 통합된 cAdvisor를 통해 가져온다. 그 다음으로 취합된 파드
리소스 사용량 통계를 metric-server 리소스 메트릭 API를 통해 노출한다. 이 API는
kubelet의 인증이 필요한 읽기 전용 포트 상의 /metrics/resource/v1beta1
에서
제공된다.
완전한 메트릭 파이프라인
완전한 메트릭 파이프라인은 보다 풍부한 메트릭에 접근할 수 있도록 해준다.
쿠버네티스는 Horizontal Pod Autoscaler와 같은 메커니즘을 활용해서 이런 메트릭에
대한 반응으로 클러스터의 현재 상태를 기반으로 자동으로 스케일링하거나 클러스터를
조정할 수 있다. 모니터링 파이프라인은 kubelet에서 메트릭을 가져와서 쿠버네티스에
custom.metrics.k8s.io
와 external.metrics.k8s.io
API를 구현한 어댑터를 통해
노출한다.
CNCF 프로젝트인, 프로메테우스는 기본적으로 쿠버네티스, 노드, 프로메테우스 자체를 모니터링할 수 있다. CNCF 프로젝트가 아닌 완전한 메트릭 파이프라인 프로젝트는 쿠버네티스 문서의 범위가 아니다.
3 - 초기화 컨테이너(Init Containers) 디버그하기
이 페이지는 초기화 컨테이너의 실행과 관련된 문제를
조사하는 방법에 대해 보여준다. 아래 예제의 커맨드 라인은 파드(Pod)를 <pod-name>
으로,
초기화 컨테이너를 <init-container-1>
과
<init-container-2>
로 표시한다.
시작하기 전에
쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음의 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.
버전 확인을 위해서, 다음 커맨드를 실행kubectl version
.- 사용자는 초기화 컨테이너의 기본 사항에 익숙해야 한다.
- 사용자는 초기화 컨테이너를 구성해야 한다.
초기화 컨테이너의 상태 체크하기
사용자 파드의 상태를 표시한다.
kubectl get pod <pod-name>
예를 들어, Init:1/2
상태는 두 개의 초기화 컨테이너 중
하나가 성공적으로 완료되었음을 나타낸다.
NAME READY STATUS RESTARTS AGE
<pod-name> 0/1 Init:1/2 0 7s
상태값과 그 의미에 대한 추가 예제는 파드 상태 이해하기를 참조한다.
초기화 컨테이너에 대한 상세 정보 조회하기
초기화 컨테이너의 실행에 대한 상세 정보를 확인한다.
kubectl describe pod <pod-name>
예를 들어, 2개의 초기화 컨테이너가 있는 파드는 다음과 같이 표시될 수 있다.
Init Containers:
<init-container-1>:
Container ID: ...
...
State: Terminated
Reason: Completed
Exit Code: 0
Started: ...
Finished: ...
Ready: True
Restart Count: 0
...
<init-container-2>:
Container ID: ...
...
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Error
Exit Code: 1
Started: ...
Finished: ...
Ready: False
Restart Count: 3
...
파드 스펙의 status.initContainerStatuses
필드를 읽어서
프로그래밍 방식으로 초기화 컨테이너의 상태를 조회할 수도 있다.
kubectl get pod nginx --template '{{.status.initContainerStatuses}}'
이 명령은 원시 JSON 방식으로 위와 동일한 정보를 반환한다.
초기화 컨테이너의 로그 조회하기
초기화 컨테이너의 로그를 확인하기 위해 파드의 이름과 초기화 컨테이너의 이름을 같이 전달한다.
kubectl logs <pod-name> -c <init-container-2>
셸 스크립트를 실행하는 초기화 컨테이너는, 초기화 컨테이너가
실행될 때 명령어를 출력한다. 예를 들어, 스크립트의 시작 부분에
set -x
를 추가하고 실행하여 Bash에서 명령어를 출력할 수 있도록 수행할 수 있다.
파드의 상태 이해하기
Init:
으로 시작하는 파드 상태는 초기화 컨테이너의
실행 상태를 요약한다. 아래 표는 초기화 컨테이너를 디버깅하는
동안 사용자가 확인할 수 있는 몇 가지 상태값의 예이다.
상태 | 의미 |
---|---|
Init:N/M | 파드가 M 개의 초기화 컨테이너를 갖고 있으며, 현재까지 N 개가 완료. |
Init:Error | 초기화 컨테이너 실행 실패. |
Init:CrashLoopBackOff | 초기화 컨테이너가 반복적으로 실행 실패. |
Pending | 파드가 아직 초기화 컨테이너를 실행하지 않음. |
PodInitializing or Running | 파드가 이미 초기화 컨테이너 실행을 완료. |
4 - 파드 실패의 원인 검증하기
이 페이지는 컨테이너 종료 메시지를 읽고 쓰는 방법을 보여준다.
종료 메시지는 컨테이너가 치명적인 이벤트에 대한 정보를, 대시보드나 모니터링 소프트웨어 도구와 같이 쉽게 조회 및 표시할 수 있는 위치에 기록하는 방법을 제공한다. 대부분의 경우에 종료 메시지에 넣는 정보는 일반 쿠버네티스 로그에도 쓰여져야 한다.
시작하기 전에
쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음의 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.
버전 확인을 위해서, 다음 커맨드를 실행kubectl version
.종료 메시지 읽기 및 쓰기
이 예제에서는, 하나의 컨테이너를 실행하는 파드를 생성한다. 하단의 설정 파일은 컨테이너가 시작될 때 수행하는 명령어를 지정한다.
apiVersion: v1
kind: Pod
metadata:
name: termination-demo
spec:
containers:
- name: termination-demo-container
image: debian
command: ["/bin/sh"]
args: ["-c", "sleep 10 && echo Sleep expired > /dev/termination-log"]
다음의 YAML 설정 파일에 기반한 파드를 생성한다.
kubectl apply -f https://k8s.io/examples/debug/termination.yaml YAML 파일에 있는 `cmd` 와 `args` 필드에서 컨테이너가 10초 간 잠든 뒤에 "Sleep expired" 문자열을 `/dev/termination-log` 파일에 기록하는 것을 확인할 수 있다. 컨테이너는 "Sleep expired" 메시지를 기록한 후에 종료된다.
파드와 관련된 정보를 출력한다.
kubectl get pod termination-demo 파드가 더 이상 실행되지 않을 때까지 앞선 명령어를 반복한다.
파드에 관한 상세 정보를 출력한다.
kubectl get pod termination-demo --output=yaml 결과는 "Sleep expired" 메시지를 포함한다. apiVersion: v1 kind: Pod ... lastState: terminated: containerID: ... exitCode: 0 finishedAt: ... message: | Sleep expired ...
종료 메시지만을 포함하는 출력 결과를 보기 위해서는 Go 템플릿을 사용한다.
kubectl get pod termination-demo -o go-template="{{range .status.containerStatuses}}{{.lastState.terminated.message}}{{end}}"
종료 메시지 사용자 정의하기
쿠버네티스는 컨테이너의 terminationMessagePath
필드에 지정된
종료 메시지 파일에서 종료 메시지를 검색하며, 이 필드의 기본값은
/dev/termination-log
이다. 이 필드를 사용자 정의 함으로써
쿠버네티스가 종료 메시지를 검색할 때 다른 파일을 사용하도록 조정할 수 있다.
쿠버네티스는 지정된 파일의 내용을 사용하여 컨테이너의 성공 및 실패에 대한 상태 메시지를 채운다.
종료 메시지는 assertion failure 메세지처럼 간결한 최종 상태로 생성된다.
kubelet은 4096 바이트보다 긴 메시지를 자른다. 모든 컨테이너의 총 메시지 길이는
12KiB로 제한된다. 기본 종료 메시지 경로는 /dev/termination-log
이다.
파드가 시작된 후에는 종료 메시지 경로를 설정할 수 없다.
다음의 예제에서 컨테이너는, 쿠버네티스가 조회할 수 있도록
/tmp/my-log
파일에 종료 메시지를 기록한다.
apiVersion: v1
kind: Pod
metadata:
name: msg-path-demo
spec:
containers:
- name: msg-path-demo-container
image: debian
terminationMessagePath: "/tmp/my-log"
또한 사용자는 추가적인 사용자 정의를 위해 컨테이너의 terminationMessagePolicy
필드를 설정할 수 있다. 이 필드의 기본 값은 File
이며,
이는 오직 종료 메시지 파일에서만 종료 메시지가 조회되는 것을 의미한다.
terminationMessagePolicy
필드의 값을 "FallbackToLogsOnError
으로
설정함으로써, 종료 메시지 파일이 비어 있고 컨테이너가 오류와 함께 종료 되었을 경우
쿠버네티스가 컨테이너 로그 출력의 마지막 청크를 사용하도록 지시할 수 있다.
로그 출력은 2048 바이트나 80 행 중 더 작은 값으로 제한된다.
다음 내용
5 - 파드와 레플리케이션컨트롤러(ReplicationController) 디버그하기
이 페이지에서는 파드와 레플리케이션컨트롤러를 디버깅하는 방법을 소개한다.
시작하기 전에
쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음의 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.
버전 확인을 위해서, 다음 커맨드를 실행kubectl version
.파드 디버깅
파드 디버깅의 첫 번째 단계는 파드를 살펴 보는 것이다. 다음의 명령어를 사용하여 파드의 현재 상태와 최근 이벤트를 점검한다.
kubectl describe pods ${POD_NAME}
파드 내부 컨테이너의 상태를 확인한다. 모두 Running
상태인가?
최근에 재시작 되었는가?
파드의 상태에 따라 디버깅을 계속한다.
파드가 pending 상태로 유지
파드가 Pending
상태로 멈춰 있는 경우는, 노드에 스케줄 될 수 없음을 의미한다.
일반적으로 이것은 어떤 유형의 리소스가 부족하거나 스케줄링을 방해하는 다른 요인 때문이다.
상단의 kubectl describe ...
명령의 결과를 확인하자.
파드를 스케줄 할 수 없는 이유에 대한 스케줄러의 메세지가 있어야 한다.
이유는 다음과 같다.
부족한 리소스
사용자 클러스터의 CPU 나 Memory의 공급이 소진되었을 수 있다. 이 경우 몇 가지 방법을 시도할 수 있다.
클러스터에 노드를 더 추가하기.
pending 상태인 파드를 위한 공간을 확보하기 위해 불필요한 파드 종료하기
파드가 노드보다 크지 않은지 확인한다. 예를 들어 모든 노드가
cpu:1
의 용량을 가지고 있을 경우,cpu: 1.1
을 요청하는 파드는 절대 스케줄 될 수 없다.사용자는
kubectl get nodes -o <format>
명령으로 노드의 용량을 점검할 수 있다. 다음은 필요한 정보를 추출하는 몇 가지 명령의 예이다.kubectl get nodes -o yaml | egrep '\sname:|cpu:|memory:' kubectl get nodes -o json | jq '.items[] | {name: .metadata.name, cap: .status.capacity}'
리소스 쿼터 기능은 사용할 수 있는 전체 리소스의 양을 제한하도록 설정할 수 있다. 네임스페이스와 함께 사용하면, 한 팀이 모든 리소스를 점유하는 것을 방지할 수 있다.
hostPort 사용하기
파드를 hostPort
에 바인딩 할 때 파드를 스케줄링 할 수 있는
위치는 제한되어 있다. 대부분의 경우 hostPort
는 불필요하다. 서비스 오브젝트를
사용하여 파드를 노출하도록 한다. hostPort
가 필요한 경우
컨테이너 클러스터에 있는 노드의 수만큼 파드를 스케줄 할 수 있다.
파드가 waiting 상태로 유지
파드가 Waiting
상태에서 멈춘 경우, 워커 노드에 스케줄 되었지만, 해당 장비에서 사용할 수 없다.
거듭 강조하지만, kubectl describe ...
의 정보는 유익하게 사용되어야 한다.
Waiting
파드의 가장 일반적인 원인은 이미지를 가져오지 못하는 경우이다.
확인해야 할 3가지 사항이 있다.
- 이미지 이름이 올바른지 확인한다.
- 이미지를 저장소에 푸시하였는가?
- 이미지가 풀 될 수 있는지 보기 위해, 사용자의 장비에서
docker pull <image>
를 수동으로 실행한다.
파드가 손상(crashing)되었거나 양호하지 않을(unhealthy) 경우
일단 사용자의 파드가 스케줄 되면, 구동중인 파드 디버그하기에 기술된 메서드를 디버깅에 사용할 수 있다.
레플리케이션컨트롤러 디버깅
레플리케이션컨트롤러는 매우 간단하다. 이 오브젝트는 파드를 만들거나 만들 수 없는 경우뿐이다. 만약 파드를 만들 수 없는 경우, 위의 지침을 참조하여 파드를 디버그한다.
사용자는 kubectl describe rc ${CONTROLLER_NAME}
을 사용하여 레플리케이션 컨트롤러와
관련된 이벤트를 검사할 수도 있다.