Kubernetes에서 동작을 확인해 보고 싶은 게 있어서 Kubernetes의 control plane의 로그를 좀 더 보고 싶었다. 실제 운영하는 클러스터의 로그 레벨을 수정할 수는 없고 수정한다고 하더라도 너무 많은 게 돌고 있어서 확인이 어려우니 로컬에서 Kubernetes 클러스터를 실행할 수 있는 kind를 써보기로 했다. kind는 이전 그룹스터디에서 다른 분이 사용하는 건 본 적이 있는데 실제로 써본 것은 처음이다.
설치 문서에 따라 설치하면 되는데 릴리스 바이너리를 다운받아서 설치했다.
클러스터는 kind create cluster
와 kind delete cluster
로 바로 만들고 지우고 할 수 있을 정도로 사용법이 쉬웠지만 나는 control plane의 옵션을 설정하고 싶어서 문서를 많이 찾아봐야 했다. 기본으로 쓰려면 그냥 명령어만 사용해도 되지만 구성 파일을 만들어서 좀 더 구체적인 설정을 할 수 있다.
클러스터 구성 파일
다음과 같이 YAML 파일을 구성해서 컨트롤 플레인 1대 워커 2대로 클러스터를 구성할 수 있는데 자세한 내용은 문서와 예시 설정 파일을 참고하면 된다.
노드에서 image
는 꼭 지정하지 않아도 되는데 나는 특정 Kubernetes 버전을 쓰고 싶어서 지정했다. 이 이미지와 SHA는 릴리스 페이지를 보면 Kubernetes 버전별로 이미지가 지정되어 있으니 이를 가져다가 사용하면 된다.
위 파일이 kind-config.yaml
라고 하면 다음과 같이 클러스터를 생성할 수 있다.
kube-controller-manager의 로그 레벨 설정
Kubernetes에서는 공유상태를 감시하면서 루프를 돌면서 컨트롤러가 처리하는데 kube-controller-manager가 이를 처리하는 데몬이다. 컨트롤러의 동작을 확인하고 싶었기에 옵션을 봤더니 -v, --v int
로 로그 레벨의 verbosity를 설정할 수 있다는 것을 알게 되었다.
Kubernetes는 로깅에 klog를 사용하는데 로깅 문서를 보면 klog.ErrorS
와 klog.InfoS
두 가지로 크게 갈리고 로그 레벨은 0~5까지 있는데 기본값을 2레벨이다. 문서에 나온 로그 레벨을 정리해 보면 다음과 같다.
klog.V(0).InfoS
=klog.InfoS
- 클러스터 운영자가 항상 볼 수 있도록 하는데 유용하다.
- 프로그래머 오류
- 패니겡 대한 추가 정보
- CLI 인자 처리
klog.V(1).InfoS
- 장황하길 원하지 않는다면 합리적인 기본 로그 레벨
- 구성에 관한 정보(X를 리스닝하고 Y를 워칭함)
- 수정할 수 있는 조건과 관련하여 자주 반복되는 오류(언헬시로 탐지된 Pod)
klog.V(2).InfoS
- 서비스에 대한 유용한 정상 상태 정보, 시스템에 중요한 변경 사항과 관련 있을 수 있는 중요한 로그 메시지가 포함된다. 대부분의 시스템에서 권장하는 기볼 로그 레벨이다.
- HTTP 요청과 종료 코드를 로깅
- 시스템 상태 변경(pod 삭제)
- 컨트롤러 상태 변경 이벤트(팟 시작)
- 스케쥴러 로그 메시지
klog.V(3).InfoS
- 변경에 관한 확장된 정보
- 시스템 상태 변경에 대한 추가 정보
klog.V(4).InfoS
- 디버그 레
- 나중에 다시 돌아와서 확인하고 싶을 수 있는 특히 까다로운 부분을 로깅
klog.V(5).InfoS
- 트레이스 레벨
- 오류와 경고로 이어지는 단계를 이해하기 위한 컨텍스트
- 보고된 이슈를 트러블슈팅하기 위한 추가 정보
이제 로깅 옵션을 알았으니 이를 클러스터에 적용해야 한다. 먼저 kube-system
네임스페이스에서 kube-controller-manager
Pod을 확인하면 kube-controller-manager
를 실행하면서 다음 옵션이 설정된 것을 확인할 수 있다. verbosity 옵션이 없는 걸로 보아 기본 레벨인 2가 적용되었다고 생각했다.
kind는 kubeadm을 사용하므로 kubeadm의 구성을 수정하는 방법을 제공하고 있다. 앞에서 작성한 kind-config.yaml
파일에 다음과 같이 kubeadmConfigPatches
를 추가했다.
설정은 간단하지만, 처음에는 어떻게 하는지 몰라서 찾는 데 좀 오래 걸렸다. 여기서 v
옵션은 숫자를 넘기지만 여기서는 문자열로 넘겨야 한다. 숫자로 넘기면 json: cannot unmarshal number into Go struct field ControlPlaneComponent.controllerManager.extraArgs of type string
오류가 발생한다.
이제 다시 클러스터를 띄운 후 kube-controller-manager
의 설정을 살펴보면 다음과 같이 마지막에 v
옵션이 추가된 것을 볼 수 있다.
kube-controller-manager
Pod의 로그를 보면 다음과 같이 로그가 남는데 로그에 로그 레벨은 표시가 안 되기 때문에 헷갈리지만 없을때와 비교하면 훨씬 많은 로그가 남겨진 것을 볼 수 있다. 이제 컨트롤러의 로그를 좀 더 상세하게 살펴볼 수 있다.
kube-apiserver의 Audit 로그 설정
Kubernetes는 모든 걸 API로 다루기 때문에 kube-apiserver
를 거쳐 가게 된다. kube-apiserver
에도 로그가 있고 로그 레벨의 verbosity를 설정할 수 있지만 kube-apiserver
에는 감사 정책을 설정할 수 있는 기능이 있다. 이 감사 로그를 기록하면 API 서버를 거치는 이벤트를 기록할 수 있다.
None
- 이 규칙에 해당하는 이벤트는 로깅 하지 않는다.Metadata
- 요청 메타데이터(요청하는 사용자, 타임스탬프, 리소스, 동사(verb) 등)는 로깅 하지만 요청/응답 본문은 로깅 하지 않는다.Request
- 이벤트 메타데이터 및 요청 본문을 로깅 하지만 응답 본문은 로깅 하지 않는다. 리소스 외의 요청에는 적용되지 않는다.RequestResponse
- 이벤트 메타데이터 및 요청/응답 본문을 로깅한다. 리소스 외의 요청에는 적용되지 않는다.
최근 트러블슈팅하면서 AWS EKS 컨트롤 플레인의 로그를 보려고 CloudWatch에서 봤던 로그도 이 감사 로그라는 것을 알게 되었다.
이를 kind에서 설정해야 했는데 다행히도 Auditing 문서가 있어서 쉽게 할 수 있었다. 먼저 아래 내용으로 audit-policy.yaml
파일을 생성한다.
너무 많아서 보기가 쉽진 않지만, 요청과 응답을 다 같이 보고 싶었기 때문에 RequestResponse
로 설정했다. 그리고 이 파일을 마운트해서 클러스터 설정에 적용되도록 kind-config.yaml
파일을 다음과 같이 수정한다.
감사로그는 kube-controller-manager
처럼 Pod의 로그가 아니라 위 설정대로 Audit 로그 파일로 컨테이너 안에 남겨지는 것이다. Kind가 로컬의 Docker를 그대로 이용하기 때문에 실행된 kind-control-plane
도커 이미지를 통해서 kube-apiserver의 Audit 로그를 다음과 같이 볼 수 있다.
추가로 로그가 너무 많아서 보기 어렵다면 kind에서 익스포트 기능을 제공해 주고 있으므로 로컬에 내려받아서 살펴볼 수 있다.
Comments