안녕하세요. 저는 클라우드 및 애자일·협업 전문 기업 오픈소스컨설팅의 이건웅이라고 합니다. 우리 회사는 클라우드, 데브옵스(DevOps), 컨테이너 아키텍처 등 인프라 관련 최신 기술 전문성을 보유, 이를 토대로 오픈스택 및 쿠버네티스 커뮤니티 오픈소스 패키지인 ‘플레이스 클라우드(Playce Cloud)’를 개발 및 공급하고 있습니다.

우리 팀은 지속적으로 CNCF의 공개 버전을 이용하여 크고 작은 사이트들에 설계, 구축 및 유지보수 업무를 진행 하고 있는데요. 이때 생기는 알찬 노하우를 공유하고자 합니다. 많은 분들이 오픈소스를 쉽게 접할 수는 있지만 실제 환경에 적용해서 사용하기에는 많은 시행 착오와 경험이 필요한데요. 누군가가 구현 가능하고 바로 사용 가능한 아키텍처를 보여준다면 너무 좋겠죠. 그래서 준비 했습니다.

구현 가능하고 적절한 사용이 가능한 Kubernetes 구축과 운영 포인트를 저와 같이 확인해 주시면 감사하겠습니다.


개요

Kubernetes는 자사 제품인 Playce Kube의 엔진 혹은 샤시로 볼 수 있는 핵심입니다. 핵심인 만큼 Kubernetes를 잘 알아야 하는데요. Playce Kube에 구축된 상태에서 Kubernetes를 설명 해보겠습니다.

Playce Kube는 kubespray로 설치되어 있고, 커뮤니티버전을 기반으로 설치 하기 때문에 Kubernetes를 커뮤니티버전으로 구축하셨다면 동일함을 미리 알려 드립니다.

Kubernetes는 Control-plane과 Worker로 구성하게 됩니다.

역할을 보자면, Control-Plane은 쿼럼(Querum)방식으로, 홀수 구조로 실질적인 Kubernetes를 컨트롤 합니다. Worker는 Container를 이용한 Pod가 운영됩니다.

그리고 Control-Plane, Worker는 1기식 구성도 가능하고, Control-Plane과 Worker가 동일 서버에 구성되어 1기의 서버에서 구성되는 k3s, Microk8s등의 경량화 구성도 가능합니다.

우리는 필요에 따라 또는 구축 성격에 따라 선택하여 구성하게 되는데요. 그렇다면 구축된 이 Kubernetes의 구조는 어떻게 되어 있을까요?

그리고 우리는 어떻게 이 시스템을 확인하고 알고 있어야 할까요? 지금부터 서버부터 천천히 살펴보도록 하겠습니다.


목표

Kubernetes를 이론적인 것이 아닌, 실제 서버에서 확인 하는 방법으로 구성과 구조를 설명 드리고 같이 이해하고자 합니다. 요약하자면 이 블로그의 목표는 엔지니어가 Kubernetes를 이해 할 수 있는 방법이라고 보면 되겠습니다.

순서는 Deploy( Vastion 서버 )에서 kubectl 명령어를 통한 서버 확인(서비스 확인이 아닙니다.), Contol-Plane에서 명령어를 통한 서버 확인, 그리고 Worker에서 명령어를 통한 서버 확인이 되겠습니다.

기준 OS는 Ubuntu 22.04환경이고 배포를 위한 deploy서버 그리고 Kubernetes의 관리를 하는 Control-Plane 3기와 Pod 운영을 위한 Worker 2기가 구성된 환경에서 각 서버의 상황을 이용하여 구조 설명을 해보겠습니다.


구축된 Kubernetes Big Picture

구조를 알아보기 위한 kubernetes는 1기의 Deploy 서버와 3기의 Control-Plane 서버, 그리고 2기의 Worker 서버로 구성되어 있습니다.

Playce Kube에 구축되어 있는 Kubernetes는 위의 그림과 같이 구성되어 있습니다.

사용되고 있는 프로그램과 Pod로 구분을 할 수 있는데요.

container를 관리 하기 위한 kubelet, kubelet이 Pod를 실행하게 되는 Runtime인 Containerd, nfs-common(ubnutu)등 이 구성됩니다.

OS구성시에 특별히 다른 어플리케이션(Ex: sshd, bind9 )들이 추가 구성 될 수 있겠지만, kubernetes에서 사용하는 기본적으로 사용하는 프로그램은 kubelet, containerd, nfs-common등이 라고 보면 되겠습니다.

계속 설명한 것 처럼 Control-Plane과 Worker로 크게 두 부분으로 서버군을 나눌 수 있겠네요.
( Deploy 서버는 기본 쿠버네티스에 포함이 되지 않습니다. )

지금 부터 각 서버군 별로 구조를 보겠습니다.


Control-Plane 구조

Control-Plane은 Kubernetes의 핵심으로 Kubernetes를 관리하는 역할을 하는데요. 그 구조를 그림으로 그리면 아래 그림과 같습니다.

우리가 인프라 시스템을 구성할 때 사용하게 되는 요소들과 Kubernetes를 관리하고 정보를 저장하는 요소들의 집합입니다. 이 중 모든 노드에 구성되는 부분과 일부 노드에만 구성되는 부분이 있는데요. 뒤에서 확인해보도록 하겠습니다.

Worker 구조

worker는 실제 서비스 하게될 Container를 Pod화 해서 사용하는 역할을 하는데요. 그 구조를 그림으로 그리면 아래 그림과 같습니다.

Pod를 실제로 운영하고 효율적인 동작을 위한 요소들로 구성되어 있습니다. Control-Plane과는 다르게 거의 모든 구성 요소가 동일하게 Worker에 구성되어 있네요. 이 부분도 뒤에서 자세히 보도록 하겠습니다.

구축만 했는데 벌서 상당히 많은 Pod들이 구성되고 운영되고 있네요. 단순히 숫자만 세어봐도 18개의 Pod가 구성되어 있는데요.

이 중에 Control-Plane의 Node와 Pod정보를 kubectl 명령어를 사용해 확인해 보겠습니다.

## Node 상태 정보
kubectl get node -o wide | grep controlplane

# NAME                        STATUS   ROLES                  AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
# playcekube-controlplane01   Ready    control-plane,master   2d4h   v1.22.8   10.0.0.21     <none>        Ubuntu 22.04.2 LTS   5.15.0-76-generic   containerd://1.5.8
# playcekube-controlplane02   Ready    control-plane,master   2d4h   v1.22.8   10.0.0.22     <none>        Ubuntu 22.04.2 LTS   5.15.0-76-generic   containerd://1.5.8
# playcekube-controlplane03   Ready    control-plane,master   2d4h   v1.22.8   10.0.0.23     <none>        Ubuntu 22.04.2 LTS   5.15.0-76-generic   containerd://1.5.8
## Pod 구성 정보
kubectl get pod -A -o wide | grep controlplane

# NAMESPACE     NAME                                                READY   STATUS             RESTARTS          AGE    IP             NODE                        NOMINATED NODE   READINESS GATES
# kube-system   calico-node-6pffs                                   1/1     Running            0                2d4h   10.0.0.22      playcekube-controlplane02   <none>           <none>
# kube-system   calico-node-bnplr                                   1/1     Running            0                2d4h   10.0.0.23      playcekube-controlplane03   <none>           <none>
# kube-system   calico-node-cw4rj                                   1/1     Running            0                2d4h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# kube-system   coredns-66fcfddbbd-4tkwd                            1/1     Running            0                2d4h   10.233.120.1   playcekube-controlplane01   <none>           <none>
# kube-system   coredns-66fcfddbbd-wvwq6                            1/1     Running            0                2d4h   10.233.118.1   playcekube-controlplane02   <none>           <none>
# kube-system   dns-autoscaler-cf845685b-njzmb                      1/1     Running            0                2d4h   10.233.121.1   playcekube-controlplane03   <none>           <none>
# kube-system   etcd-playcekube-controlplane01                      1/1     Running            1                2d4h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# kube-system   etcd-playcekube-controlplane02                      1/1     Running            1                2d4h   10.0.0.22      playcekube-controlplane02   <none>           <none>
# kube-system   etcd-playcekube-controlplane03                      1/1     Running            1                2d4h   10.0.0.23      playcekube-controlplane03   <none>           <none>
# kube-system   kube-apiserver-playcekube-controlplane01            1/1     Running            1                2d4h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# kube-system   kube-apiserver-playcekube-controlplane02            1/1     Running            2                2d4h   10.0.0.22      playcekube-controlplane02   <none>           <none>
# kube-system   kube-apiserver-playcekube-controlplane03            1/1     Running            2                2d4h   10.0.0.23      playcekube-controlplane03   <none>           <none>
# kube-system   kube-controller-manager-playcekube-controlplane01   1/1     Running            3                2d4h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# kube-system   kube-controller-manager-playcekube-controlplane02   1/1     Running            2                2d4h   10.0.0.22      playcekube-controlplane02   <none>           <none>
# kube-system   kube-controller-manager-playcekube-controlplane03   1/1     Running            2                2d4h   10.0.0.23      playcekube-controlplane03   <none>           <none>
# kube-system   kube-proxy-6bbrp                                    1/1     Running            0                2d3h   10.0.0.23      playcekube-controlplane03   <none>           <none>
# kube-system   kube-proxy-ngkdb                                    1/1     Running            0                2d3h   10.0.0.22      playcekube-controlplane02   <none>           <none>
# kube-system   kube-proxy-r4dc5                                    1/1     Running            0                2d3h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# kube-system   kube-scheduler-playcekube-controlplane01            1/1     Running            3                2d4h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# kube-system   kube-scheduler-playcekube-controlplane02            1/1     Running            2                2d4h   10.0.0.22      playcekube-controlplane02   <none>           <none>
# kube-system   kube-scheduler-playcekube-controlplane03            1/1     Running            2                2d4h   10.0.0.23      playcekube-controlplane03   <none>           <none>
# kube-system   metrics-server-7855bfbc9b-9mlkw                     1/1     Running            0                2d3h   10.233.121.2   playcekube-controlplane03   <none>           <none>
# playcekube    csi-nfs-node-75sd8                                  3/3     Running            0                2d3h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# playcekube    csi-nfs-node-jxnbf                                  3/3     Running            0                2d3h   10.0.0.22      playcekube-controlplane02   <none>           <none>
# playcekube    csi-nfs-node-s6mjd                                  3/3     Running            0                2d3h   10.0.0.23      playcekube-controlplane03   <none>           <none>

위에서 보았던 Control-Plane의 그림과 같이 Node와 Pod가 정상적으로 잘 구성되어 있습니다. 단순히 두 개의 명령어로 구성을 확인해 보았는데요. kubernetes는 kubectl 명령어를 통해 API 통신으로 운영에 대한 모든 정보를 획득 할 수 있습니다.

매우 편리한 시스템이네요. 물론 GUI 환경도 제공이 됩니다만, 서버의 환경과 정보도 확인해야 하는 만큼 CLI환경에서 계속 살펴 보겠습니다.

위에서 살펴본 Kubernetes의 Control-Plane정보중에 상태 정보는 Running 이지만 실제로 모든 작동의 이상유무를 확인하는 명령어는 따로 있습니다.

## Event 정보  
kubectl get event -n kube-system

# No resources found in kube-system namespace.
## Log 정보
kubectl logs -l tier=control-plane -n kube-system --all-containers=true

# No resources found in kube-system namespace.
*lable을 확인하는 명령어: kubectl describe pod -n kube-system kube-apiserver-playcekube-controlplane01 | grep Labels
## Pod별 Log확인
kubectl logs -n kube-system kube-apiserver-playcekube-controlplane01
kubectl logs -n kube-system kube-apiserver-playcekube-controlplane02
kubectl logs -n kube-system kube-apiserver-playcekube-controlplane03
:
:
kubectl logs -n kube-system kube-scheduler-playcekube-controlplane01
kubectl logs -n kube-system kube-scheduler-playcekube-controlplane02
kubectl logs -n kube-system kube-scheduler-playcekube-controlplane03

컨테이너의 로그들이 생각보다 상세히 나오네요. 자주 확인해서 Log들에 익숙해져야 겠습니다.

Linux 환경 ( Ubuntu OS )에서 확인은 당연히 할 수 있어야 하는데요. 지금부터 Linux Processor로 확인 해보겠습니다. 엔지니어들에게는 이 부분이 상당히 중요하겠죠? 지금부터 집중해서 보겠습니다. Control-Plane01을 대상으로 살펴 보도록 하겠습니다.

## Control-Plane01 
## kube-system Pod 확인
kubectl  get pod -A  -o wide  | grep -E 'playcekube-controlplane01|NAME'

# NAMESPACE     NAME                                                READY   STATUS    RESTARTS       AGE    IP             NODE                        NOMINATED NODE   READINESS GATES
# kube-system   calico-node-cw4rj                                   1/1     Running   0              2d9h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# kube-system   coredns-66fcfddbbd-4tkwd                            1/1     Running   0              2d9h   10.233.120.1   playcekube-controlplane01   <none>           <none>
# kube-system   etcd-playcekube-controlplane01                      1/1     Running   1              2d9h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# kube-system   kube-apiserver-playcekube-controlplane01            1/1     Running   1              2d9h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# kube-system   kube-controller-manager-playcekube-controlplane01   1/1     Running   3              2d9h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# kube-system   kube-proxy-r4dc5                                    1/1     Running   0              2d8h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# kube-system   kube-scheduler-playcekube-controlplane01            1/1     Running   3              2d9h   10.0.0.21      playcekube-controlplane01   <none>           <none>
# playcekube    csi-nfs-node-75sd8                                  3/3     Running   0              2d8h   10.0.0.21      playcekube-controlplane01   <none>           <none>

Control-Plane01 노드에서 kube-apiserver 를 찾아 보도록 하겠습니다. 이름이 ‘kube-apiserver-playcekube-controlplane01’ 입니다.

## Container Pod 확인 
crictl pods

# POD ID              CREATED             STATE               NAME                                                NAMESPACE           ATTEMPT             RUNTIME
# 36245675f3bc2       44 hours ago        Ready               kube-controller-manager-playcekube-controlplane01   kube-system         0                   (default)
# 0721a35df516c       44 hours ago        Ready               kube-scheduler-playcekube-controlplane01            kube-system         1                   (default)
# 4b942abe81e38       44 hours ago        Ready               kube-apiserver-playcekube-controlplane01            kube-system         1                   (default)
# acaf7a698d5de       44 hours ago        Ready               etcd-playcekube-controlplane01                      kube-system         1                   (default)
# 8507eb8d3474f       2 days ago          Ready               csi-nfs-node-75sd8                                  playcekube          0                   (default)
# bbe8f839d9520       2 days ago          Ready               kube-proxy-r4dc5                                    kube-system         0                   (default)
# fdcbe57b8d766       2 days ago          Ready               coredns-66fcfddbbd-4tkwd                            kube-system         0                   (default)
# 887e0cda927ab       2 days ago          Ready               calico-node-cw4rj                                   kube-system         0                   (default)

crictl 명령어로 Pod를 확인해보니 우리가 kubectl 명령어로 본것과 동일 하다는 것을 알 수 있습니다. 그럼 Container상태를 볼까요?

## Container Process 확인
crictl ps

# CONTAINER           IMAGE               CREATED             STATE               NAME                      ATTEMPT             POD ID
# 7a537cf6943d9       41ff053508988       44 hours ago        Running             kube-controller-manager   3                   36245675f3bc2
# 98fb36a5799ac       c0d565df2c900       44 hours ago        Running             kube-apiserver            1                   4b942abe81e38
# 23e9e80264c94       398b2c18375df       44 hours ago        Running             kube-scheduler            3                   0721a35df516c
# 06e79f97b9343       a7908fd5fb88f       44 hours ago        Running             etcd                      1                   acaf7a698d5de
# b0de3c27fd96d       b1d3401f372c2       2 days ago          Running             nfs                       0                   8507eb8d3474f
# 2d5a9a8085ce3       cb03930a2bd42       2 days ago          Running             node-driver-registrar     0                   8507eb8d3474f
# 0e2344eba696d       8b6940b4f6952       2 days ago          Running             liveness-probe            0                   8507eb8d3474f
# 60cfdc5651e84       c1cfbd59f7747       2 days ago          Running             kube-proxy                0                   bbe8f839d9520
# 4ca0a7d889669       296a6d5035e2d       2 days ago          Running             coredns                   0                   fdcbe57b8d766
# c1eb5a0d173e1       6570786a0fd3b       2 days ago          Running             calico-node               0                   887e0cda927ab

이름으로 보면 ‘kube-apiserver’ 가 ‘kube-apiserver-playcekube-controlplane01’ 로 유추는 가능하지만 동일하지는 않네요. 그럼 무엇으로 정확하게 찾을 수 있을까요? 네. 바로 ‘POD ID’입니다.

‘kube-apiserver-playcekube-controlplane01′ 에 해당하는 POD ID는 ‘4b942abe81e38’ 입니다. 그리고 여기에 포함하는 CONTAINER는 ’98fb36a5799ac’이고 IMAGE는 ‘c0d565df2c900’라는 것을 알 수 있습니다.

이것을 확인하는 방법은 아주 중요합니다. 지금 kube-apiserver의 경우 1개의 Pod에 1개의 Container만 존재 하지만 ‘csi-nfs-node-75sd8’를 보게 된다면, 1개의 Pod( ‘8507eb8d3474f’ )에 3개의 Container( ‘b1d3401f372c2’, ‘cb03930a2bd42’, ‘8b6940b4f6952’ )가 존재 하는 것을 알 수 있습니다.

그렇다면 container 명령어가 아닌 Linux에서 주로 사용하는 ‘ps’ 명령어로는 어떻게 확인 할 수 있을까요?

## Processor 확인
ps -ef | grep -E 'kube|conta' | cut -c -150 | grep -v grep 

# UID          PID    PPID  C STIME TTY          TIME CMD
# root       21096       1  0 Oct01 ?        00:30:53 /usr/local/bin/containerd
# root       25835       1  3 Oct01 ?        01:59:20 /usr/local/bin/kubelet --logtostderr=true --v=2 --node-ip=10.0.0.21 --hostname-override=playcekube
# root       27523       1  0 Oct01 ?        00:08:04 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 887e0cda927ab8980de82f34fdb4348f314f5
# root       29883       1  0 Oct01 ?        00:01:14 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id fdcbe57b8d766c13317cc1e0ae573a5758376
# root       44428       1  0 Oct01 ?        00:01:14 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id bbe8f839d95206730eaa4eb2467c259f17de2
# root       44474   44428  0 Oct01 ?        00:07:27 /usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/config.conf --hostname-override=playcekube-
# root       48297       1  0 Oct01 ?        00:09:47 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 8507eb8d3474f848df7861a00bdcc4a203eaa
# root       48393   48297  0 Oct01 ?        00:00:06 /csi-node-driver-registrar --v=2 --csi-address=/csi/csi.sock --kubelet-registration-path=/var/lib/
# root       48472   48297  0 Oct01 ?        00:00:27 /nfsplugin --v=5 --nodeid=playcekube-controlplane01 --endpoint=unix:///csi/csi.sock --drivername=n
# root      527147       1  0 Oct02 ?        00:01:01 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id acaf7a698d5de0295f41ccb6c781a9ae6189d
# root      527177       1  0 Oct02 ?        00:00:58 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 0721a35df516c11315d4e64a6b79a65661049
# root      527179       1  0 Oct02 ?        00:01:00 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 4b942abe81e3850da73f75859f5f953b1c4e9
# root      527285  527147  5 Oct02 ?        02:32:12 etcd --advertise-client-urls=https://10.0.0.21:2379 --auto-compaction-retention=8 --cert-file=/etc
# root      527329  527177  0 Oct02 ?        00:13:05 kube-scheduler --authentication-kubeconfig=/etc/kubernetes/scheduler.conf --authorization-kubeconf
# root      527345  527179  9 Oct02 ?        04:22:06 kube-apiserver --advertise-address=10.0.0.21 --allow-privileged=true --anonymous-auth=True --apise
# root      527393       1  0 Oct02 ?        00:00:57 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 36245675f3bc215bab6e273b1ac19dd72c1d7
# root      527468  527393  0 Oct02 ?        00:06:06 kube-controller-manager --allocate-node-cidrs=true --authentication-kubeconfig=/etc/kubernetes/con

여기서부터는 조금 복잡합니다. 구분하여서 보여드리겠습니다.

프로세서 구분

  • pid(21096): containerd – 실제 컨테이너를 기동하는 Runtime 입니다.
  • pid(25835): kubelet – Pod의 상태를 컨트롤러에 업데이트 하고 Container를 운영합니다.
    ( 프로세서로 systemd에서 관리 됩니다. )
  • pid(527285): etcd – kubernetes의 정보를 key: value방식으로 저장하고 운영됩니다.
    ( Container로 운영됩니다. 부모 PID로 527147(containerd)를 갖고 있습니다.
  • pid(527345): kube-apiserver – Containerd의 pid(527179)의 자식 쓰레드, Container가 실행한 프로세서 입니다.
  • pid(527179): kube-apiserver containerd – 실행 명령어 중에 ID 부분 ‘4b942abe81e3850da73f75859f5f953b1c4e9’ 앞부분 13자리는 crictl 로 확인 가능한 Pod ID입니다.

자 이제 Pod ID로 Linux Processor까지 찾을 수 있게 되었습니다. 그러면 이제 Control-Plane은 편안하게 Linux Processor보듯이 보면 되겠습니다.

Worker의 processor 또한 동일한 방법으로 확인 할 수 있습니다. 다만 Worker에서는 kubectl 명령어가 되지 않습니다. Pod 확인은 Bastion Node 혹은 Control-Planed에서 확인하시기 바랍니다.

## Control-Plane01 
## kube-system Pod 확인
kubectl  get pod -A  -o wide  | grep -E 'playcekube-worker01|NAME'

NAMESPACE     NAME                                                READY   STATUS    RESTARTS        AGE     IP             NODE                        NOMINATED NODE   READINESS GATES
default       nginx                                               1/1     Running   0               21h     10.233.99.5    playcekube-worker01         <none>           <none>
default       nginx-deployment-84cd76b964-lzldz                   1/1     Running   0               21h     10.233.99.4    playcekube-worker01         <none>           <none>
kube-system   calico-kube-controllers-b8d4d8984-8htc7             1/1     Running   1 (2d10h ago)   2d10h   10.0.0.31      playcekube-worker01         <none>           <none>
kube-system   calico-node-zdvr6                                   1/1     Running   0               2d10h   10.0.0.31      playcekube-worker01         <none>           <none>
kube-system   kube-proxy-9dq5c                                    1/1     Running   0               2d10h   10.0.0.31      playcekube-worker01         <none>           <none>
kube-system   nginx-proxy-playcekube-worker01                     1/1     Running   0               2d10h   10.0.0.31      playcekube-worker01         <none>           <none>
playcekube    csi-nfs-node-pzd8b                                  3/3     Running   0               2d10h   10.0.0.31      playcekube-worker01         <none>           <none>
playcekube    ingress-nginx-controller-lwtdv                      1/1     Running   0               2d10h   10.233.99.1    playcekube-worker01         <none>           <none>

Worker Node에는 네트워크와 스토리지 관련 Pod가 생성되어 있습니다. Container에서 확인해보겠습니다.

Worker01 Node에서 calico-node 를 찾아 보도록 하겠습니다. 이름이 ‘calico-node-zdvr6’ 입니다.

## Worker01
## Container Pod 확인 
crictl pods

# POD ID              CREATED             STATE               NAME                                      NAMESPACE           ATTEMPT             RUNTIME
# dfffc3ef49458       22 hours ago        Ready               nginx                                     default             0                   (default)
# fdf9daf39cb9e       22 hours ago        Ready               nginx-deployment-84cd76b964-lzldz         default             0                   (default)
# 7a85f61b52e4e       2 days ago          Ready               csi-nfs-node-pzd8b                        playcekube          0                   (default)
# 83748bfb3e8b0       2 days ago          Ready               ingress-nginx-controller-lwtdv            playcekube          0                   (default)
# 0f9045064331c       2 days ago          Ready               kube-proxy-9dq5c                          kube-system         0                   (default)
# ec6e557854405       2 days ago          Ready               calico-kube-controllers-b8d4d8984-8htc7   kube-system         0                   (default)
# 0af961b44dfcb       2 days ago          Ready               calico-node-zdvr6                         kube-system         0                   (default)
# b86eb16363b44       2 days ago          Ready               nginx-proxy-playcekube-worker01           kube-system         0                   (default)

crictl 명령어로 Pod를 확인해보니 역시 동일합니다. 그럼 Container상태를 볼까요?

## Container Process 확인
crictl ps

# CONTAINER           IMAGE               CREATED             STATE               NAME                      ATTEMPT             POD ID
# 97e8981b68e4f       61395b4c586da       22 hours ago        Running             nginx                     0                   dfffc3ef49458
# 79a5ad26ab862       61395b4c586da       22 hours ago        Running             nginx                     0                   fdf9daf39cb9e
# 22120d672d2d0       b1d3401f372c2       2 days ago          Running             nfs                       0                   7a85f61b52e4e
# c613ae1a069d3       cb03930a2bd42       2 days ago          Running             node-driver-registrar     0                   7a85f61b52e4e
# 54e2e1cd6b9ed       8b6940b4f6952       2 days ago          Running             liveness-probe            0                   7a85f61b52e4e
# d3475e4fecbcb       75bdf78d9d67e       2 days ago          Running             controller                0                   83748bfb3e8b0
# 21519adb1ea55       c1cfbd59f7747       2 days ago          Running             kube-proxy                0                   0f9045064331c
# ea89243281d34       fcd3512f2a7c5       2 days ago          Running             calico-kube-controllers   1                   ec6e557854405
# a07cb04ea0486       6570786a0fd3b       2 days ago          Running             calico-node               0                   0af961b44dfcb
# 033b5209eb3e8       f6987c8d6ed59       2 days ago          Running             nginx-proxy               0                   b86eb16363b44

이름으로 보면 ‘calico-node’ 가 ‘calico-node-zdvr6’ 로 보입니다. 역시 동일합니다. 당연히 POD ID도 동일합니다.

Processor도 확인 해보겠습니다.

## Processor 확인
ps -ef | grep -E 'kube|conta' | cut -c -150 | grep -v grep 

# UID          PID    PPID  C STIME TTY          TIME CMD
# root       21520       1  1 Oct01 ?        00:46:32 /usr/local/bin/containerd
# root       23947       1  0 Oct01 ?        00:01:30 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id b86eb16363b447c6c1fcb850d54b43f1e5190
# root       24742       1  0 Oct01 ?        00:10:56 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 0af961b44dfcb7423b3bb8119ecbeec33dfe9
# root       25768       1  2 Oct01 ?        01:45:48 /usr/local/bin/kubelet --logtostderr=true --v=2 --node-ip=10.0.0.31 --hostname-override=playcekube
# root       26048       1  0 Oct01 ?        00:07:43 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id ec6e557854405ee2b3a2b4209f601fe06365c
# lxd        26193   26048  0 Oct01 ?        00:18:54 /usr/bin/kube-controllers
# root       43695       1  0 Oct01 ?        00:01:29 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 0f9045064331c8376ba4f37b3fc8fb6b5694d
# root       43749   43695  0 Oct01 ?        00:09:30 /usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/config.conf --hostname-override=playcekube-
# root       46484       1  0 Oct01 ?        00:01:33 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 83748bfb3e8b0f577caca0a132d6d26ee6db2
# systemd+   46778   46484  0 Oct01 ?        00:00:00 /usr/bin/dumb-init -- /nginx-ingress-controller --election-id=ingress-controller-leader --controll
# systemd+   46791   46778  0 Oct01 ?        00:04:43 /nginx-ingress-controller --election-id=ingress-controller-leader --controller-class=k8s.io/ingres
# root       47319       1  0 Oct01 ?        00:11:09 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id 7a85f61b52e4e7bcf28592f0f682402e8c553
# root       47478   47319  0 Oct01 ?        00:00:09 /csi-node-driver-registrar --v=2 --csi-address=/csi/csi.sock --kubelet-registration-path=/var/lib/
# root       47543   47319  0 Oct01 ?        00:00:32 /nfsplugin --v=5 --nodeid=playcekube-worker01 --endpoint=unix:///csi/csi.sock --drivername=nfs.csi
# root     2033930       1  0 Oct03 ?        00:00:31 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id fdf9daf39cb9ed8217e4257670f2a72324999
# root     2037009       1  0 Oct03 ?        00:00:33 /usr/local/bin/containerd-shim-runc-v2 -namespace k8s.io -id dfffc3ef49458fff93da4f8cafd2b7559df89

동일하게 PID와 PPID를 통해서 확인 및 점검이 가능하겠습니다.

그럼 위에서 확인한 Image ID를 어디서 확인 할 수 있는지도 보겠습니다.

## Worker01
## Image ID 확인 
crictl ps | grep calico-node

# CONTAINER           IMAGE               CREATED             STATE               NAME                      ATTEMPT             POD ID
# a07cb04ea0486       6570786a0fd3b       2 days ago          Running             calico-node               0                   0af961b44dfcb

## Image 확인 
crictl images

# IMAGE                                                             TAG                   IMAGE ID            SIZE
# docker.io/library/nginx                                           latest                61395b4c586da       70.5MB
# registry.local.cloud:5000/bitnami/keycloak                        18.0.0-debian-10-r6   5e458924be421       591MB
# registry.local.cloud:5000/calico/cni                              v3.20.3               e9a8982d9e894       48.4MB
# registry.local.cloud:5000/calico/kube-controllers                 v3.20.3               fcd3512f2a7c5       26.1MB
# registry.local.cloud:5000/calico/node                             v3.20.3               6570786a0fd3b       64.9MB
# registry.local.cloud:5000/calico/pod2daemon-flexvol               v3.20.3               0631af1a04ae8       9.36MB
# registry.local.cloud:5000/coreos/etcd                             v3.5.0                a7908fd5fb88f       40.6MB
# registry.local.cloud:5000/ingress-nginx/controller                v1.2.1                75bdf78d9d67e       107MB
# registry.local.cloud:5000/kube-apiserver                          v1.22.8               c0d565df2c900       31.3MB
# registry.local.cloud:5000/kube-controller-manager                 v1.22.8               41ff053508988       29.8MB
# registry.local.cloud:5000/kube-proxy                              v1.22.8               c1cfbd59f7747       36MB
# registry.local.cloud:5000/kube-scheduler                          v1.22.8               398b2c18375df       15MB
# registry.local.cloud:5000/library/nginx                           1.21.4                f6987c8d6ed59       56.7MB
# registry.local.cloud:5000/pause                                   3.3                   0184c1613d929       298kB
# registry.local.cloud:5000/sig-storage/csi-node-driver-registrar   v2.5.0                cb03930a2bd42       9.13MB
# registry.local.cloud:5000/sig-storage/livenessprobe               v2.6.0                8b6940b4f6952       8.24MB
# registry.local.cloud:5000/sig-storage/nfsplugin                   v4.0.0                b1d3401f372c2       38.7MB

crictl 명령어를 통해 보게되면 Registry를 통해 Node에 다운로드한 Image를 확인 할 수 있습니다. 이 이미지 이름으로 Pod를 구동 할 수 있으니 잘 알고 있어야 합니다. 이미지를 통해 Container가 작동하므로 정상적으로 다운로드가 되었는지, TAG와 SIZE가 같은지 지속적으로 확인을 해봐야 합니다.


Log 경로 확인

Kubernetes는 각 Node의 Containerd와 kubelet으로 동작하고 있습니다. systemctl로 동작하는 만큼 “/var/log”의 경로에 저장하고 있습니다.

## Worker01
## Log 경로
pwd && ls

# /var/log

# alternatives.log    chrony                   kern.log           syslog                  
# apt                 containers               landscape          ubuntu-advantage.log 
# auth.log            dmesg                    lastlog            unattended-upgrades
# btmp                dpkg.log                 pods               wtmp
# calico              journal                  private              

이중에서 사용되는 Log의 경로는 “/var/log/calico”, “/var/log/containers”, “/var/log/pods”, “/var/log/syslog” 입니다.

  • /var/log/calico == cni의 Log 입니다. calico가 사용하는 cni의 Log가 적재됩니다.
  • /var/log/containers == Container의 Log 입니다. 실제로는 /var/log/pods의 경로로 링크되어 있습니다.
  • /var/log/pods == Pod의 Log 입니다. “kube-system_calico-node-zdvr6_dc05646b-058d-48e9-94c3-b4e19ebc2262” 처럼 하위 경로에 Pod 이름으로 디렉토리가 생성되고 Log가 적재됩니다.
  • /var/log/syslog == kubelet의 Log가 적제됩니다. ‘journalctl -u kubelet –since today’ 혹은 ‘tail -100 syslog | grep kubelet’ 등으로 확인이 가능합니다.

Pod 별로 Log가 증가하므로 Directory의 관리가 중요하겠습니다.


주요 Kubernetes 설정 파일 경로

Kubernetes의 설정 파일과 인증서는 각 Node별로 관리 되고있습니다. 경로는 각 Node의 “/etc/kubernetes”경로에 저장되어 사용됩니다.

## Worker01
## 설정 및 인증서 경로 
pwd && ls

# /etc/kubernetes
 
# kubeadm-client.conf            kubelet.conf              manifests         pki
# kubelet-config.yaml            kubelet.env               ssl

이 경로의 파일들은 모두 중요합니다. 각 Node의 구성과 Kubernetes의 설정 파일, 그리고 인증서가 보관되고 있습니다. 그리고 “/etc/kubernetes/manifests”의 경로에는 Static Pod를 구동하는 Yaml파일들이 있습니다.

## Manifests 확인 
pwd && ls 

# /etc/kubernetes/manifests

# nginx-proxy.yml

Worker01에서 구동되고 있던 Pod중 nginx-proxy는 Static Pod로 구동되어 있다는 것을 알게 되었네요.

*주의 Manifests의 Yaml파일은 수정하고 저장하는 즉시 적용됩니다. 적용에 주의 하시기 바랍니다.

결론

Kubernetes의 구조를 System의 관점에서 바라보았습니다. 생각보다 심플해 보이네요. 물론 각 각의 구성요소들의 동작요소를 조금더 깊게 봐야 하겠지만, 큰 숲을 보고 나무를 보듯이 큰 틀에서부터 컴포넌트들의 연동 구조까지 깊게 봐야 하겠습니다.

kubectl을 통해서 kubernetes를 보고, Containerd에서 구동이 되어 있고, Processor에서 확인 할 수 있게 되었습니다.

이렇게 구조를 알게 되면, 서비스의 사용과 운용에 많은 도움이 될 것입니다.

추가로 Log를 확인하면서 장애 대비와 구성 파일들을 확인하면서, 탄력적인 사용과 업그레이드를 대비 할 수 있게 됩니다.

매일 보고, 잘 사용할 수 있게 스킬업을 해야겠습니다.

kubectl과 Linux 명령어를 통해 Kubernetes에 빨리 익숙해졌으면 합니다.

Kubernetes란 무엇인가를 시작으로, 고객의 니즈와 서비스 형태를 바탕으로 완성한 쿠버네티스 시스템을 분석하여 블로깅 하고 있습니다.
우리 모두 오픈소스컨설팅의 미션 처럼 기술을 나누고, 모두 함께 성장했으면 좋겠습니다.


참고사이트

kubectl 명령어

Kubernetes Components

쿠버네티스-위키백과

CNCF 홈페이지

Playce Kube github

Hey guys Hi guys I'm Gunwoong, a technical engineer. I'm dreaming of technology development that everyone can use.

Leave a Reply

Your email address will not be published. Required fields are marked *