1. Kubelet
1.1. 정의
kubelet은 각 노드에서 실행되는 기본 노드 에이전트다. api-server와 통신하며,
podspec을 사용해 podspec에 기술된 컨테이너들이 정상적으로 작동되도록
돕는다. Worker Node가 배라면 kubelet은 선장과 같은 역할을 맞는다고 할 수 있다.
관리자가 pod을 배포하려고 할 경우, api-server를 비롯한 컨트롤 플레인의
컴포넌트들은 명령에 대한 인가 및 인증을 수행하고, 선언된 상태와 일치하지 않는 pod가 있는지 확인하며, 어떤 노드에 pod을 배치하면 좋을지를 결정한다.
배치하는 역할은 컨트롤 플레인의 스케줄러가 결정하지만 실제로 컨테이너
런타임에 배치를 명령하는 것은 kubelet의 역할이다. 만약 kubelet이 정지되면
컨테이너 런타임에 요청을 보내는 역할을 수행해주는 컴포넌트가 정지 되었으므로,
pod 생성, 삭제 등이 해당 노드에서 정상적으로 수행되지 못한다.
1.2. 동작 확인
kubelet은 Worker Node 안에서 동작하는 서비스 형태이기 때문에 해당 노드에
들어가 systemctl status kubelet을 통해 확인할 수 있다.
admin@node2:~$ systemctl status kubelet ● kubelet.service - Kubernetes Kubelet Server Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2023-08-09 08:44:28 KST; 1h 27min ago Docs: https://github.com/GoogleCloudPlatform/kubernetes Main PID: 1150 (kubelet) Tasks: 13 (limit: 9379) Memory: 127.0M CPU: 1min 13.079s CGroup: /system.slice/kubelet.service └─1150 /usr/local/bin/kubelet --v=2 --node-ip=192.168.180.50 --hostname-override=node2 --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --config=/etc/kube> 8월 09 10:11:20 node2 kubelet[1150]: E0809 10:11:20.615785 1150 pod_workers.go:965] "Error syncing pod, skipping" err="failed to \"StartContainer\" for \"node-cache\" with Cras> 8월 09 10:11:22 node2 kubelet[1150]: I0809 10:11:22.615713 1150 scope.go:115] "RemoveContainer" containerID="6c4de391b272bf7a5304f4416cd899587baed5ddb4b35c0a092ed58d9e1bbb97" |
# 컨테이너 런타임에 배치하는게 kubelet이라서 정지된다면 해당 노드에 pod가 생성되지 못한다. # kubelet이 정지되어 있다. admin@node2:~$ systemctl status kubelet ○ kubelet.service - Kubernetes Kubelet Server Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: enabled) Active: inactive (dead) since Wed 2023-08-09 10:12:28 KST; 6s ago [admin@controlnode bash_completion.d (kubernetes-admin@cluster.local:default)]$ kubectl run nginx1 --image nginx pod/nginx1 created [admin@controlnode bash_completion.d (kubernetes-admin@cluster.local:default)]$ kgp NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx 0/1 ImagePullBackOff 0 88s 10.233.102.140 node1 <none> <none> nginx1 0/1 Pending 0 75s <none> node2 <none> <none> # nginx1 이름의 pod을 생성했지만 배치되지 못한다. [admin@controlnode bash_completion.d (kubernetes-admin@cluster.local:default)]$ k describe pod nginx1 Status: Pending Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 1m default-scheduler Successfully assigned default/nginx1 to node2 # 자세히 보면 event에서 node2에 배치된 것을 확인할 수 있지만 상태는 배치되지 못한 pending 상태를 유지하는 것을 확인할 수 있다. admin@node2:~$ sudo systemctl start kubelet [admin@controlnode bash_completion.d (kubernetes-admin@cluster.local:default)]$ kgp NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx 0/1 ImagePullBackOff 0 2m17s 10.233.102.140 node1 <none> <none> nginx1 0/1 ImagePullBackOff 0 2m7s 10.233.75.13 node2 <none> <none> # kubelet을 실행한 뒤 다시 상태를 보면 이미지가 없어 불러올 수는 없지만 컨테이너 런타임에는 배치된 것을 확인할 수 있다. |
1.3. static pod 생성
kubelet을 활용하면 해당 노드에 정적으로 pod을 생성하는 static pod을 설정할 수 있다. 해당 pod은 kube-apiserver에 의하지 않고 kubelet이 pod를 생성 및 관리하는 것이 특징이다. 단, static pod은 pod 생성만 가능하고 레플리카 셋 등 다른 리소스는 생성이 불가능하다.
# staticPodPath를 통해 static pod을 생성할 수 있는 경로 확인 admin@node2:~$ cat /var/lib/kubelet/config.yaml apiVersion: kubelet.config.k8s.io/v1beta1 authentication: anonymous: enabled: false webhook: cacheTTL: 0s enabled: true x509: clientCAFile: /etc/kubernetes/ssl/ca.crt authorization: mode: Webhook webhook: cacheAuthorizedTTL: 0s cacheUnauthorizedTTL: 0s cgroupDriver: systemd clusterDNS: - 169.254.25.10 clusterDomain: cluster.local cpuManagerReconcilePeriod: 0s evictionPressureTransitionPeriod: 0s fileCheckFrequency: 0s healthzBindAddress: 127.0.0.1 healthzPort: 10248 httpCheckFrequency: 0s imageMinimumGCAge: 0s kind: KubeletConfiguration logging: flushFrequency: 0 options: json: infoBufferSize: "0" verbosity: 0 memorySwap: {} nodeStatusReportFrequency: 0s nodeStatusUpdateFrequency: 0s resolvConf: /run/systemd/resolve/resolv.conf rotateCertificates: true runtimeRequestTimeout: 0s shutdownGracePeriod: 0s shutdownGracePeriodCriticalPods: 0s staticPodPath: /etc/kubernetes/manifests streamingConnectionIdleTimeout: 0s syncFrequency: 0s volumeStatsAggPeriod: 0s # static pod을 생성할 yaml 파일 생성해서 staticPodPath로 이동 [admin@controlnode ~ (kubernetes-admin@cluster.local:default)]$ kubectl run nginx --image nginx --dry-run=client -o yaml > nginx.yaml [admin@controlnode ~ (kubernetes-admin@cluster.local:default)]$ scp nginx.yaml node2:/tmp nginx.yaml 100% 232 236.7KB/s 00:00 admin@node2:~$ sudo mv /tmp/nginx.yaml /etc/kubernetes/manifests/ # yaml파일을 static pod path로 이동하자마자 kubelet에 의해 pod 생성 확인 [admin@controlnode ~ (kubernetes-admin@cluster.local:default)]$ kgp NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-node2 0/1 ImagePullBackOff 0 35s 10.233.75.14 node2 <none> <none> # control node에서 생성한 pod과 달리 pod 이름 뒤에 hostname이 붙으며, Controlled By Node/node2 로 출력되는 것을 확인할 수 있다. [admin@controlnode ~ (kubernetes-admin@cluster.local:default)]$ k describe pod nginx-node2 Name: nginx-node2 Namespace: default Priority: 0 Node: node2/192.168.180.50 Controlled By: Node/node2 # Control Node에서 생성한 pod의 경우 service Account가 출력되며 controlled By가 없는것을 확인할 수 있다. [admin@controlnode ~ (kubernetes-admin@cluster.local:default)]$ k describe pod nginx Name: nginx Namespace: default Priority: 0 Service Account: default Node: node1/192.168.180.40 |
static pod의 경우 staticPodPath에 yaml 파일이 존재할 경우 자동으로 생성되며,
yaml을 수정할 시 자동으로 기존 pod가 삭제되고 새로운 pod가 생성된다. 해당
경로의 yaml을 삭제하는 경우 pod 또한 즉시 삭제된다.