Kubernetes 컨트롤러의 상세한 동작을 확인하고 싶은 일이 있었다. 로그 레벨을 올려서 확인해 보았지만, 모든 로그가 남는 건 아니어서 원하는 세부 사항을 파악하긴 어려웠다.
결국 동작을 제대로 확인하려면 컨트롤러에 직접 로그를 추가해서 돌려봐야 알 수 있겠다는 생각이 들었다. 이전에 스터디했던(당시에 잘 이해 못 했지만) kubebuilder를 이용해서 Kuberentes의 컨트롤러를 올려보려고 했지만, 커스텀 컨트롤러를 만드는 프레임워크라서 내용도 복잡해서 몇 시간 문서를 보고 파악해 보려다가 포기했다. Kubernetes의 컨트롤러를 그대로 가져와서 띄우고 싶은 거라 내가 필요한 것보다 내용이 복잡했다.
그다음으로는 Kubernets에서 sample-controller 예제를 제공하고 있어서 이를 확인해 봤다. 예전 스터디할 때도 비슷하게 했던 기억이 났는데 sample-controller를 이용하면 로컬에서 띄운 컨트롤러를 연결해서 동작을 확인해 볼 수 있으므로 더 쉽게 확인할 수 있을 것 같았다. sample-controller 자체는 쉽게 연결할 수 있었는데 Kubernetes의 컨트롤러 소스 코드를 sample-controller 형태로 가져오는 게 쉽지 않았다. Kubernetes 전체 프로젝트에 연결된 의존성도 있어서 더 어려웠기에 반대로 Kubernetes 소스 코드 안에 있는 컨트롤러 코드를 sample-controller처럼 수정해서 컨트롤러를 빌드하려고 시도했으나 이마저도 실패했다. 내가 Go 언어에 대한 지식이 더 많았다면 가능했을지도 모르지만 나한테는 쉽지 않았다.
kubebuilder나 sample-controller나 단일 CRD와 컨트롤러를 만들어서 연결하는데 Kubernetes에 내장 컨트롤러는 kube-controller-manager로 합쳐져서 빌드되기 때문에 내 지식으론 따로 빌드하기가 쉽지 않았다. 컨트롤러도 각각 개발해야 하니 Kuberentes 프로젝트에 개별 컨트롤러를 빌드해서 테스트하는 방법이 있을 것 같았는데 문서를 찾지는 못했다.
Kind의 노드 이미지 직접 생성하기
결국 내가 원하는 건 내가 추가 로깅을 하도록 수정한 컨트롤러를 Kubernetes 클러스터 내에서 실행하는 것이므로 수정한 코드로 띄울 수만 있다면 kube-controller-manager를 다 새로 띄워도 크게 상관없고 동작 면에서 오히려 이게 더 나을 수도 있었다. CronJob을 테스트하려는 거라 CRD 대신 내장된 리소스를 써야 하는 부분도 있었다. 그래서 Kind에서 직접 빌드한 Kubernetes 이미지를 사용하는 법을 찾아봤다.
Kind에서는 아래처럼 control-plane이나 work에서 사용할 Kubernetes 이미지를 지정하고 이는 Kind 릴리스 공지에 버전 안내가 나와 있다.
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
image: kindest/node:v1.24.7@sha256:577c630ce8e509131eab1aea12c022190978dd2f745aac5eb1fe65c0807eb315
- role: worker
image: kindest/node:v1.24.7@sha256:577c630ce8e509131eab1aea12c022190978dd2f745aac5eb1fe65c0807eb315
Node Image 문서를 보면 노드 이미지를 직접 빌드하는 방법이 나와 있다.(이것저것 찾아볼 때 보긴 했는데 문서가 자세히 나와 있진 않아서 넘어갔다) kind에서 친절하게도 직접 Kubernetes 이미지에서 노드 이미지를 빌드할 수 있는 kind build node-image
명령어를 제공한다.
$ kind build node-image -h
Build the node image which contains Kubernetes build artifacts and other kind requirements
Usage:
kind build node-image [kubernetes-source] [flags]
Flags:
--arch string architecture to build for, defaults to the host architecture
--base-image string name:tag of the base image to use for the build (default "docker.io/kindest/base:v20221025-014d1502")
-h, --help help for node-image
--image string name:tag of the resulting image to be built (default "kindest/node:latest")
--kube-root string DEPRECATED: please switch to just the argument. Path to the Kubernetes source directory (if empty, the path is autodetected)
--type string build type, default is docker (default "docker")
Global Flags:
--loglevel string DEPRECATED: see -v instead
-q, --quiet silence all stderr output
-v, --verbosity int32 info log verbosity, higher value produces more output
이전에는 --kube-root
플래그를 썼던 것 같지만 이젠 명령어 인자로 Kubernetes 소스의 위치를 전달하면 된다.
빌드를 위해 kubernetes 소스 코드를 클론 받고 내가 원하는 버전인 v1.24.10
로 바꾸었다.
$ git clone https://github.com/kubernetes/kubernetes
$ git checkout v1.24.10
이제 kubernetes 소스 코드가 있는 곳에서 kind build node-image ./
로 이미지를 빌드한다. 다른 곳에서 실행한다면 마지막 인자로 소스 코드의 경로를 지정하면 된다.
$ kind build node-image ./
Starting to build Kubernetes
+++ [0320 01:07:07] Verifying Prerequisites....
+++ [0320 01:07:07] Using docker on macOS
+++ [0320 01:07:07] Building Docker image kube-build:build-9be49182ee-5-v1.24.0-go1.19.5-bullseye.0
+++ [0320 01:07:10] Syncing sources to container
+++ [0320 01:07:11] Running build command...
+++ [0320 01:07:14] Building go targets for linux/arm64
k8s.io/kubernetes/hack/make-rules/helpers/go2make (non-static)
+++ [0320 01:07:18] Generating prerelease lifecycle code for 26 targets
+++ [0320 01:07:21] Generating deepcopy code for 236 targets
+++ [0320 01:07:24] Generating defaulter code for 92 targets
+++ [0320 01:07:30] Generating conversion code for 129 targets
+++ [0320 01:07:39] Generating openapi code for KUBE
+++ [0320 01:07:54] Generating openapi code for AGGREGATOR
+++ [0320 01:07:55] Generating openapi code for APIEXTENSIONS
+++ [0320 01:07:56] Generating openapi code for CODEGEN
+++ [0320 01:07:57] Generating openapi code for SAMPLEAPISERVER
+++ [0320 01:07:58] Building go targets for linux/arm64
k8s.io/kubernetes/cmd/kube-apiserver (static)
k8s.io/kubernetes/cmd/kube-controller-manager (static)
k8s.io/kubernetes/cmd/kube-scheduler (static)
k8s.io/kubernetes/cmd/kube-proxy (static)
k8s.io/kubernetes/cmd/kubeadm (static)
k8s.io/kubernetes/cmd/kubectl (static)
k8s.io/kubernetes/cmd/kubelet (non-static)
+++ [0320 01:08:12] Syncing out of container
+++ [0320 01:08:16] Building images: linux-arm64
+++ [0320 01:08:16] Starting docker build for image: kube-apiserver-arm64
+++ [0320 01:08:16] Starting docker build for image: kube-controller-manager-arm64
+++ [0320 01:08:16] Starting docker build for image: kube-scheduler-arm64
+++ [0320 01:08:16] Starting docker build for image: kube-proxy-arm64
+++ [0320 01:08:23] Deleting docker image registry.k8s.io/kube-scheduler-arm64:v1.24.10-dirty
+++ [0320 01:08:23] Deleting docker image registry.k8s.io/kube-proxy-arm64:v1.24.10-dirty
+++ [0320 01:08:25] Deleting docker image registry.k8s.io/kube-controller-manager-arm64:v1.24.10-dirty
+++ [0320 01:08:25] Deleting docker image registry.k8s.io/kube-apiserver-arm64:v1.24.10-dirty
+++ [0320 01:08:25] Docker builds done
Finished building Kubernetes
Building node image ...
Building in container: kind-build-1679242110-1920456844
Image "kindest/node:latest" build completed.
마지막 메시지에서 보듯이 kindest/node:latest
로 빌드되고 kind는 로컬의 Docker를 그대로 사용하므로 이 이미지를 사용할 수 있다.
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
image: kindest/node:latest
- role: worker
image: kindest/node:latest
이제 kind create cluster --config kind-config.yaml
로 클러스터를 생성하고 kube-controller-manager
의 로그를 확인하면 아래처럼 수정된 로그(Starting cronjob controller v2
를 Starting custom cronjob controller v2
로 변경했다.)를 확인할 수 있다.
I0319 16:05:33.714932 1 controllermanager.go:564] Starting "cronjob"
I0319 16:05:33.717930 1 controllermanager.go:593] Started "cronjob"
I0319 16:05:33.717994 1 cronjob_controllerv2.go:135] "Starting custom cronjob controller v2"
Comments