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

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

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



목표

Kubernetes를 사용함에 있어, 관리하게 되는 Kube-APIServer, Kube-Controller, Kube-Scheduler, etcd, kubelet, kube-proxy, CNI, CSI, nginx-ingress, service, Pod, Object 등의 상당히 많은 요소들을 알고, 학습해야 할 필요가 있습니다.

Kubernetes를 일반 개발자, 혹은 사업관리자들은 Container Orchstration으로 자동 배포, 자동 수평확장, 자동 복구가 되는 시스템으로만 알고 있지만 이러한 것들은 아무런 댓가 없이 이루어지지는 않습니다.
Kubernetes를 잘 이해하는 엔지니어가 사용방법과 운영방법을 어드바이스하고 지속적인 확인과 점검을 할 필요가 있지요.

그러기 위해서 엔지니어들은 Kubernetes의 요소들을 잘 숙지하고, 365일 24시간 주 7일의 안정적인 운영에 최선의 노력을 경주해야 겠지요. 그렇다면, 문제없는 관리를 위해 Kubernetes의 구성요소들을 살펴보겠습니다.

Playce Kube에서 제공하는 CNI(Calico)의 구성 형태와 확인 방법을 통해 Pod 간 통신을 확인하고, Pod 네트워크를 이해 할 수 있도록 하겠습니다.


CNI 란?

Kubernetes의 CNI는 여러 프로젝트가 진행되고 있지만, 프로젝트의 확장과 사용이 용이한 Calico를 Playce Kube에서는 사용하고 있습니다. 그럼 CNI(Container Network Interface)란 무엇인지 알아야 하는데요, CNI는 컨테이너간의 네트워크를 제어할 수 있는 플러그인을 뜻합니다. 
 요약하자면, 물리 환경의 네트워크를 기반으로 하여, Container Runtime에서 Container간의 네트워크를 사용하게 도와주는 인터페이스 입니다.  

 CNI는 여러 플러그인들이 존재 하며, 주로 Container의 네트워크 연결과 Container삭제에 따른 리소스제거가 주요 기능으로 뚜렷하고 확실한 목표가 있어, 광범위한 지원을 제공하고 요구사항을 구현하기가 간단합니다. 우리가 알고있는 네트워크를 생각한다면, L2인지 L3인지 그리고 TCP/UDP를 지원하고 Inbound/Outbound를 제어해주는 것으로 보면 되겠습니다. 

Calico 란?

 Calico CNI Architecture

Calico Architecture

 Calico는 다양한 환경에서 운영이 가능하지만, Playce Kube에서 제공되는 Kubernetes의 환경을 중점으로 보겠습니다. Calico는 다양한 환경에서 운영이 가능한 만큼 다양한 설정이 준비되어 있습니다. Kubernetes와 관련을 뽑자면 네트워크 플러그인서비스, 로드벨런싱 그리고 네트워킹 등에서 자세히 지정하고 사용하게 되어있습니다.


당연히 Calico는 Kubernetes가 요구하는 네트워크 정책을 완벽히 지원한다고 합니다. 그렇다면 우리는 Calico만 잘 이해하면, Playce Kube의 네트워크 환경을 잘 이해 할 수 있겠네요.
 위의 구조도는 Calico 홈페이지에서 설명하는 Architecture지만, 상세 설명이나 정확히 어떻게 움직이는지는 보이지 않네요. 물론 Calico를 이미 통달하신 분은 이 한장의 구조도를 보고 ‘충분하다’라고 생각할 수 있을 것입니다. 그러나 단번에 알아보기는 쉽지 않아보입니다.

각 Node별로 네트워크에 필요한 프로그램들과 호스트별로 Pod구성을 칼리코가 관리 하면서, Calico는 Control-Plane Node와 통신하며 작동 하는 것으로 보입니다.

구성된 Calico를 Playce kube의 Control-Plane에서 좀더 상세하게 확인 해보도록 하겠습니다.

 

 Calico 구성 정보 확인 

 Playce Kube에서 구축된 내역을 확인해 보겠습니다. Control-Plane의 1, 2, 3 어디에서도 확인이 가능합니다. (Worker에서는 확인이 되지 않습니다.)

### Calico CNI 정보 확인 
# calicoctl version
Client Version:    v3.20.3
Git commit:        dcb4b76a
Cluster Version:   v3.20.3
Cluster Type:      kubespray,bgp,kubeadm,kdd,k8s

### Node 상태 확인 
# calicoctl node status
Calico process is running.

IPv4 BGP status
+--------------+-------------------+-------+----------+-------------+
| PEER ADDRESS |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+--------------+-------------------+-------+----------+-------------+
| 10.0.0.22    | node-to-node mesh | up    | 14:28:46 | Established |
| 10.0.0.23    | node-to-node mesh | up    | 14:30:06 | Established |
| 10.0.0.31    | node-to-node mesh | up    | 14:30:45 | Established |
| 10.0.0.32    | node-to-node mesh | up    | 14:28:54 | Established |
+--------------+-------------------+-------+----------+-------------+

IPv6 BGP status
No IPv6 peers found.

### ip pool 정보 확인 
# calicoctl get ippool -o wide
NAME           CIDR             NAT    IPIPMODE   VXLANMODE   DISABLED   DISABLEBGPEXPORT   SELECTOR
default-pool   10.233.64.0/18   true   Always     Never       false      false              all()

### calico 설정 Yaml 형태로 확인
# calicoctl get ippool default-pool -o yaml 

apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  creationTimestamp: "2023-05-10T15:12:42Z"
  name: default-pool
  resourceVersion: "1162"
  uid: c84e11a9-3621-4880-8d66-f8e988ea255b
spec:
  blockSize: 24
  cidr: 10.233.64.0/18
  ipipMode: Always
  natOutgoing: true
  nodeSelector: all()
  vxlanMode: Never
              

### 생성된 파드에 대한 위치, 정보 확인
# calicoctl get workloadEndpoint

WORKLOAD                                   NODE                  NETWORKS           INTERFACE
nginx-deployment-84cd76b964-jnt76          playcekube-worker02   10.233.106.12/32   cali382bc0c1cbe
nginx-volume-deployment-69c9474d89-dbgm4   playcekube-worker02   10.233.106.14/32   calif31b03684db
nginx-volume-deployment-69c9474d89-hh48q   playcekube-worker01   10.233.99.10/32    cali146ae769172
nginx-volume-deployment-69c9474d89-jjxfr   playcekube-worker01   10.233.99.9/32     cali6d8b6ed7fbf
nginx-volume-deployment-69c9474d89-mlwgc   playcekube-worker02   10.233.106.13/32   cali37dd35672f6
nginx-volume-deployment-69c9474d89-v6zdm   playcekube-worker01   10.233.99.11/32    cali7d09eb87bd4

 Calico의 버전부터 Node의 상태, 그리고 할당 가능한 Pod IP Address의 범위 등등 Calico는 간단한 명령어를 통해 확인이 가능한 것이 생각보다 많습니다.

확인한 내역들은 위에서부터 간단하게 설명하자면, Version은 항상 호환성을 위해서라도 확인하는 것이 좋습니다. OpenSource들은 최신 버전의 생성과 생명주기가 제품별로 다를 수 있기때문에 항상 확인하는 습관이 있어야 하겠습니다. 설치된 Calico는 3.20.3 버전이네요.

노드 스테이터스는 총 4개의 PEER ADDRESS가 보이는데 검색을 한 서버는 보이지 않는것 같습니다. 특이한 점이네요.

그리고 BGP를 사용하고, IP Pool 은 10.233.64.0의 18비트 (subnet 255.255.192.0, 16384 hosts)를 사용하고 있습니다. ( Kubernetes 기본 설정 )

 IP Pool의 설정을 yaml 형태로 본다면 더 정확히 보입니다. default-pool 이라는 이름으로 10.233.64/18과 ipipMode항목이 Always라고 명시되어 있네요. IP in IP 모드는 Pod간의 통신을 IP Address 기반의 터널링 방식으로 사용 한다는 것이고, 터널링을 사용하게 될 경우에는 Pod 네트워크 패킷의 기존 IP헤더 앞에 IP헤더를 하나 더 붙여서 통신하게 됩니다. 즉 MTU(Maximum Transmission Unit) 1500byte를 다 사용하지 못한다는 것이죠. 이 부분은 뒤에서 더 보도록 하겠습니다.

 그럼 정보를 더 보도록 하겠습니다. 

 Calico Pod 정보 확인 

### Calico Pod 정보
# kubectl -n kube-system get all | grep calico
pod/calico-kube-controllers-b8d4d8984-82xn7       1/1     Running   79 (30m ago)    46d
pod/calico-node-8qf8n                             1/1     Running   1 (30m ago)     46d
pod/calico-node-92vqx                             1/1     Running   1 (31m ago)     46d
pod/calico-node-l42l9                             1/1     Running   1 (32m ago)     46d
pod/calico-node-sn89s                             1/1     Running   1 (29m ago)     46d
pod/calico-node-zx9z6                             1/1     Running   1 (31m ago)     46d
daemonset.apps/calico-node   5         5         5       5            5           kubernetes.io/os=linux   46d
deployment.apps/calico-kube-controllers   1/1     1            1           46d
replicaset.apps/calico-kube-controllers-b8d4d8984   1         1         1       46d

## Calico Node의 Pod(calico-node-8qf8n) 상세 정보
# kubectl -n kube-system describe pod calico-node-8qf8n

ame:                 calico-node-8qf8n
Namespace:            kube-system
Priority:             2000001000
Priority Class Name:  system-node-critical
Node:                 playcekube-master03/10.0.0.13
Start Time:           Thu, 11 May 2023 00:13:00 +0900
Labels:               controller-revision-hash=96f798dc5
                      k8s-app=calico-node
                      pod-template-generation=1
Annotations:          <none>
Status:               Running
IP:                   10.0.0.13
IPs:
  IP:           10.0.0.13
Controlled By:  DaemonSet/calico-node
Init Containers:
  upgrade-ipam:
    Container ID:  containerd://697ee3795ce25ea231d6e942a21f872ff8448493931f78ba4b04cd3d3ffbccec
    Image:         registry.local.cloud:5000/calico/cni:v3.20.3
    Image ID:      sha256:e9a8982d9e894ca1030928298cee1d8064f6e082e174e99fe359b728de5e92a9
    Port:          <none>
    Host Port:     <none>
    Command:
      /opt/cni/bin/calico-ipam
      -upgrade
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Mon, 26 Jun 2023 23:29:35 +0900
      Finished:     Mon, 26 Jun 2023 23:29:37 +0900
    Ready:          True
    Restart Count:  1
    Environment Variables from:
      kubernetes-services-endpoint  ConfigMap  Optional: true
    Environment:
      KUBERNETES_NODE_NAME:        (v1:spec.nodeName)
      CALICO_NETWORKING_BACKEND:  <set to the key 'calico_backend' of config map 'calico-config'>  Optional: false
    Mounts:
      /host/opt/cni/bin from cni-bin-dir (rw)
      /var/lib/cni/networks from host-local-net-dir (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-twqbd (ro)
  install-cni:
    Container ID:  containerd://9c154e8b8a742a8dd826fa9e480f317b79c2e6408e1857884cd5dff0efb903bf
    Image:         registry.local.cloud:5000/calico/cni:v3.20.3
    Image ID:      sha256:e9a8982d9e894ca1030928298cee1d8064f6e082e174e99fe359b728de5e92a9
    Port:          <none>
    Host Port:     <none>
    Command:
      /opt/cni/bin/install
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Mon, 26 Jun 2023 23:29:45 +0900
      Finished:     Mon, 26 Jun 2023 23:29:52 +0900
    Ready:          True
    Restart Count:  0
    Environment Variables from:
      kubernetes-services-endpoint  ConfigMap  Optional: true
    Environment:
      CNI_CONF_NAME:            10-calico.conflist
      UPDATE_CNI_BINARIES:      true
      CNI_NETWORK_CONFIG_FILE:  /host/etc/cni/net.d/calico.conflist.template
      SLEEP:                    false
      KUBERNETES_NODE_NAME:      (v1:spec.nodeName)
    Mounts:
      /host/etc/cni/net.d from cni-net-dir (rw)
      /host/opt/cni/bin from cni-bin-dir (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-twqbd (ro)
  flexvol-driver:
    Container ID:   containerd://da7937ee27926d01e7ec9b198711a05926c87f5f50d7504016713cd88bfc1b72
    Image:          registry.local.cloud:5000/calico/pod2daemon-flexvol:v3.20.3
    Image ID:       sha256:0631af1a04ae8074a3a0ceb5aeec688f19aa71627c9118b60391dd1158e37eb9
    Port:           <none>
    Host Port:      <none>
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Mon, 26 Jun 2023 23:29:54 +0900
      Finished:     Mon, 26 Jun 2023 23:29:54 +0900
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /host/driver from flexvol-driver-host (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-twqbd (ro)
Containers:
  calico-node:
    Container ID:   containerd://1ab8efb046edf5e10247a9daf394e2a9ec5f536e7309abf947ebc94338ceae36
    Image:          registry.local.cloud:5000/calico/node:v3.20.3
    Image ID:       sha256:6570786a0fd3b9950d85ee3b26046fa07930eb4599023603b9e33809f0d51f43
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Mon, 26 Jun 2023 23:29:55 +0900
    Last State:     Terminated
      Reason:       Unknown
      Exit Code:    255
      Started:      Thu, 11 May 2023 00:13:25 +0900
      Finished:     Mon, 26 Jun 2023 23:29:08 +0900
    Ready:          True
    Restart Count:  1
    Limits:
      cpu:     300m
      memory:  500M
    Requests:
      cpu:      150m
      memory:   64M
    Liveness:   exec [/bin/calico-node -felix-live -bird-live] delay=10s timeout=10s period=10s #success=1 #failure=6
    Readiness:  exec [/bin/calico-node -bird-ready -felix-ready] delay=0s timeout=10s period=10s #success=1 #failure=6
    Environment Variables from:
      kubernetes-services-endpoint  ConfigMap  Optional: true
    Environment:
      DATASTORE_TYPE:                         kubernetes
      WAIT_FOR_DATASTORE:                     true
      CALICO_NETWORKING_BACKEND:              <set to the key 'calico_backend' of config map 'calico-config'>  Optional: false
      CLUSTER_TYPE:                           <set to the key 'cluster_type' of config map 'calico-config'>    Optional: false
      CALICO_K8S_NODE_REF:                     (v1:spec.nodeName)
      CALICO_DISABLE_FILE_LOGGING:            true
      FELIX_DEFAULTENDPOINTTOHOSTACTION:      RETURN
      FELIX_HEALTHHOST:                       localhost
      FELIX_IPTABLESBACKEND:                  Legacy
      FELIX_IPTABLESLOCKTIMEOUTSECS:          10
      CALICO_IPV4POOL_IPIP:                   Off
      FELIX_IPV6SUPPORT:                      False
      FELIX_LOGSEVERITYSCREEN:                info
      CALICO_STARTUP_LOGLEVEL:                error
      FELIX_USAGEREPORTINGENABLED:            False
      FELIX_CHAININSERTMODE:                  Insert
      FELIX_PROMETHEUSMETRICSENABLED:         False
      FELIX_PROMETHEUSMETRICSPORT:            9091
      FELIX_PROMETHEUSGOMETRICSENABLED:       True
      FELIX_PROMETHEUSPROCESSMETRICSENABLED:  True
      NODEIP:                                  (v1:status.hostIP)
      IP_AUTODETECTION_METHOD:                can-reach=$(NODEIP)
      IP:                                     autodetect
      NODENAME:                                (v1:spec.nodeName)
      FELIX_HEALTHENABLED:                    true
      FELIX_IGNORELOOSERPF:                   False
      CALICO_MANAGE_CNI:                      true
    Mounts:
      /host/etc/cni/net.d from cni-net-dir (rw)
      /lib/modules from lib-modules (ro)
      /run/xtables.lock from xtables-lock (rw)
      /var/lib/calico from var-lib-calico (rw)
      /var/log/calico/cni from cni-log-dir (ro)
      /var/run/calico from var-run-calico (rw)
      /var/run/nodeagent from policysync (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-twqbd (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  lib-modules:
    Type:          HostPath (bare host directory volume)
    Path:          /lib/modules
    HostPathType:
  var-run-calico:
    Type:          HostPath (bare host directory volume)
    Path:          /var/run/calico
    HostPathType:
  var-lib-calico:
    Type:          HostPath (bare host directory volume)
    Path:          /var/lib/calico
    HostPathType:
  cni-net-dir:
    Type:          HostPath (bare host directory volume)
    Path:          /etc/cni/net.d
    HostPathType:
  cni-bin-dir:
    Type:          HostPath (bare host directory volume)
    Path:          /opt/cni/bin
    HostPathType:
  xtables-lock:
    Type:          HostPath (bare host directory volume)
    Path:          /run/xtables.lock
    HostPathType:  FileOrCreate
  host-local-net-dir:
    Type:          HostPath (bare host directory volume)
    Path:          /var/lib/cni/networks
    HostPathType:
  cni-log-dir:
    Type:          HostPath (bare host directory volume)
    Path:          /var/log/calico/cni
    HostPathType:
  policysync:
    Type:          HostPath (bare host directory volume)
    Path:          /var/run/nodeagent
    HostPathType:  DirectoryOrCreate
  flexvol-driver-host:
    Type:          HostPath (bare host directory volume)
    Path:          /usr/libexec/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds
    HostPathType:  DirectoryOrCreate
  kube-api-access-twqbd:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Burstable
Node-Selectors:              kubernetes.io/os=linux
Tolerations:                 op=Exists
                             node.kubernetes.io/disk-pressure:NoSchedule op=Exists
                             node.kubernetes.io/memory-pressure:NoSchedule op=Exists
                             node.kubernetes.io/network-unavailable:NoSchedule op=Exists
                             node.kubernetes.io/not-ready:NoExecute op=Exists
                             node.kubernetes.io/pid-pressure:NoSchedule op=Exists
                             node.kubernetes.io/unreachable:NoExecute op=Exists
                             node.kubernetes.io/unschedulable:NoSchedule op=Exists
Events:                      <none>

## Calico Controller의 Pod(calico-kube-controllers-b8d4d8984-82xn7) 상세 정보
# kubectl -n kube-system describe pod calico-kube-controllers-b8d4d8984-82xn7
Name:                 calico-kube-controllers-b8d4d8984-82xn7
Namespace:            kube-system
Priority:             2000000000
Priority Class Name:  system-cluster-critical
Node:                 playcekube-worker02/10.0.0.21
Start Time:           Thu, 11 May 2023 00:14:04 +0900
Labels:               k8s-app=calico-kube-controllers
                      pod-template-hash=b8d4d8984
Annotations:          <none>
Status:               Running
IP:                   10.0.0.21
IPs:
  IP:           10.0.0.21
Controlled By:  ReplicaSet/calico-kube-controllers-b8d4d8984
Containers:
  calico-kube-controllers:
    Container ID:   containerd://e76406836d05657e20361e436984100ab18a9c4707c44f0f21150be77a3518d3
    Image:          registry.local.cloud:5000/calico/kube-controllers:v3.20.3
    Image ID:       sha256:fcd3512f2a7c5b023f9e6997545b9b0d71504e574fc77e2146524ad5b96a4204
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Mon, 26 Jun 2023 23:28:44 +0900
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1
      Started:      Mon, 26 Jun 2023 23:28:24 +0900
      Finished:     Mon, 26 Jun 2023 23:28:28 +0900
    Ready:          True
    Restart Count:  79
    Limits:
      cpu:     1
      memory:  256M
    Requests:
      cpu:      30m
      memory:   64M
    Liveness:   exec [/usr/bin/check-status -l] delay=10s timeout=1s period=10s #success=1 #failure=6
    Readiness:  exec [/usr/bin/check-status -r] delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:
      ENABLED_CONTROLLERS:  node
      DATASTORE_TYPE:       kubernetes
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-lf7sd (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  kube-api-access-lf7sd:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Burstable
Node-Selectors:              kubernetes.io/os=linux
Tolerations:                 node-role.kubernetes.io/control-plane:NoSchedule
                             node-role.kubernetes.io/master:NoSchedule
                             node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:                      <none>

 이번에는 Pod의 정보입니다. 생각보다 많은 정보가 있어서 놀랄 수 있는데요. 우리가 간단히 사용 할 수 있게 되어 있다고 해도 역시 내부에서는 많은 정보를 갖고, 많은 작용이 이루어 지고 있는것으로 보입니다. 한줄씩 다 보면 좋겠지만 상당한 시간이 필요해 보이네요. 이중 중요해 보이는 부분만 집고 넘어가겠습니다. 

 Calico는 크게 1개의 Deployment와 이를 통해 생성되는 Replicaset이 있고 Replicaset은 calico-kube-controllers를 생성하고, 1개의 Daemonset은 모든 Node에 calico-node를 생성하고 있습니다. 두 파드 모두 성능부분이 지정되어 있고, Liveness와 Readiness가 있어 라이프사이클이 관리 됨을 알 수 있습니다. 

 Controller의 경우 특별한 설정이 보이지 않지만 실제로 일하게 되는 calico-node는 상당히 긴 정보가 표시되는데요. 이중에 enviroment와 mount를 보면 설정과 옵션들이 있습니다. 

 mount는 주로 로그와 실행파일 그리고 lock등의 경로에 관련이 있어 보입니다. 그럼 Environment를 보겠습니다. 이 중에서 큰 이름들을 본다면, Felix, Calico등이 있네요. 크게 두가지의 설정들을 지정한 것 같습니다. Calico는 글로벌한 설정으로 보이고, Felix는 상세 값을 가진 설정으로 보입니다. 아마 실제 Calico안에서 직접적으로 작동을 하는것으로 보입니다. 

 아직은 정확한 설정을 알 수 없네요. Pod별 설정이므로 실제 설정들을 확인해 보겠습니다.      

 Calico 설정 정보 확인 

### Config Map 확인 
# kubectl  get cm -n kube-system | grep cali
calico-config                        2      47d

# kubectl  get cm -n kube-system calico-config -o yaml
apiVersion: v1
data:
  calico_backend: bird
  cluster_type: kubespray,bgp
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"calico_backend":"bird","cluster_type":"kubespray,bgp"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"calico-config","namespace":"kube-system"}}
  creationTimestamp: "2023-05-10T15:12:55Z"
  name: calico-config
  namespace: kube-system
  resourceVersion: "1210"
  uid: 4b685c6f-08d7-4a00-881c-a2c15262524b

# 노드 설정 파일 확인 
# pwd
/etc/kubernetes

# ls -alhtr cali*
-rw-r--r-- 1 root root  151 May 11 00:12 calico-config.yml
-rw-r--r-- 1 root root  11K May 11 00:12 calico-node.yml
-rw-r--r-- 1 root root   95 May 11 00:12 calico-node-sa.yml
-rw-r--r-- 1 root root 3.4K May 11 00:12 calico-cr.yml
-rw-r--r-- 1 root root  265 May 11 00:12 calico-crb.yml
-rw-r--r-- 1 root root 1.6K May 11 00:13 calico-kube-controllers.yml
-rw-r--r-- 1 root root  107 May 11 00:13 calico-kube-sa.yml
-rw-r--r-- 1 root root 1.6K May 11 00:13 calico-kube-cr.yml
-rw-r--r-- 1 root root  301 May 11 00:14 calico-kube-crb.yml

# cat calico-config.yml
kind: ConfigMap
apiVersion: v1
metadata:
  name: calico-config
  namespace: kube-system
data:
  cluster_type: "kubespray,bgp"
  calico_backend: "bird"

# cat calico-node.yml 
---
# This manifest installs the calico/node container, as well
# as the Calico CNI plugins and network config on
# each master and worker node in a Kubernetes cluster.
kind: DaemonSet
apiVersion: apps/v1
metadata:
  name: calico-node
  namespace: kube-system
  labels:
    k8s-app: calico-node
spec:
  selector:
    matchLabels:
      k8s-app: calico-node
  template:
    metadata:
      labels:
        k8s-app: calico-node
      annotations:
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      priorityClassName: system-node-critical
      hostNetwork: true
      serviceAccountName: calico-node
      tolerations:
      - operator: Exists
      # Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force
      # deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods.
      terminationGracePeriodSeconds: 0
      initContainers:
        # This container performs upgrade from host-local IPAM to calico-ipam.
        # It can be deleted if this is a fresh installation, or if you have already
        # upgraded to use calico-ipam.
        - name: upgrade-ipam
          image: registry.local.cloud:5000/calico/cni:v3.20.3
          command: ["/opt/cni/bin/calico-ipam", "-upgrade"]
          envFrom:
            - configMapRef:
                # Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
                name: kubernetes-services-endpoint
                optional: true
          env:
            - name: KUBERNETES_NODE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: CALICO_NETWORKING_BACKEND
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: calico_backend
          volumeMounts:
            - mountPath: /var/lib/cni/networks
              name: host-local-net-dir
            - mountPath: /host/opt/cni/bin
              name: cni-bin-dir
          securityContext:
            privileged: true
        # This container installs the Calico CNI binaries
        # and CNI network config file on each node.
        - name: install-cni
          image: registry.local.cloud:5000/calico/cni:v3.20.3
          command: ["/opt/cni/bin/install"]
          envFrom:
          - configMapRef:
              # Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
              name: kubernetes-services-endpoint
              optional: true
          env:
            # Name of the CNI config file to create.
            - name: CNI_CONF_NAME
              value: "10-calico.conflist"
            # Install CNI binaries
            - name: UPDATE_CNI_BINARIES
              value: "true"
            # The CNI network config to install on each node.
            - name: CNI_NETWORK_CONFIG_FILE
              value: "/host/etc/cni/net.d/calico.conflist.template"
            # Prevents the container from sleeping forever.
            - name: SLEEP
              value: "false"
            # Set the hostname based on the k8s node name.
            - name: KUBERNETES_NODE_NAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
          volumeMounts:
            - mountPath: /host/etc/cni/net.d
              name: cni-net-dir
            - mountPath: /host/opt/cni/bin
              name: cni-bin-dir
          securityContext:
            privileged: true
        # Adds a Flex Volume Driver that creates a per-pod Unix Domain Socket to allow Dikastes
        # to communicate with Felix over the Policy Sync API.
        - name: flexvol-driver
          image: registry.local.cloud:5000/calico/pod2daemon-flexvol:v3.20.3
          volumeMounts:
            - name: flexvol-driver-host
              mountPath: /host/driver
          securityContext:
            privileged: true
      containers:
        # Runs calico/node container on each Kubernetes node.  This
        # container programs network policy and routes on each
        # host.
        - name: calico-node
          image: registry.local.cloud:5000/calico/node:v3.20.3
          envFrom:
            - configMapRef:
                # Allow KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT to be overridden for eBPF mode.
                name: kubernetes-services-endpoint
                optional: true
          env:
            # The location of the Calico etcd cluster.
            # Use Kubernetes API as the backing datastore.
            - name: DATASTORE_TYPE
              value: "kubernetes"
            # Wait for the datastore.
            - name: WAIT_FOR_DATASTORE
              value: "true"
            # Choose the backend to use.
            - name: CALICO_NETWORKING_BACKEND
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: calico_backend
            # Cluster type to identify the deployment type
            - name: CLUSTER_TYPE
              valueFrom:
                configMapKeyRef:
                  name: calico-config
                  key: cluster_type
            # Set noderef for node controller.
            - name: CALICO_K8S_NODE_REF
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            # Disable file logging so `kubectl logs` works.
            - name: CALICO_DISABLE_FILE_LOGGING
              value: "true"
            # Set Felix endpoint to host default action to ACCEPT.
            - name: FELIX_DEFAULTENDPOINTTOHOSTACTION
              value: "RETURN"
            - name: FELIX_HEALTHHOST
              value: "localhost"
            - name: FELIX_IPTABLESBACKEND
              value: "Legacy"
            - name: FELIX_IPTABLESLOCKTIMEOUTSECS
              value: "10"
# should be set in etcd before deployment
#            # Configure the IP Pool from which Pod IPs will be chosen.
#            - name: CALICO_IPV4POOL_CIDR
#              value: "10.233.64.0/18"
            - name: CALICO_IPV4POOL_IPIP
              value: "Off"
            - name: FELIX_IPV6SUPPORT
              value: "False"
            # Set Felix logging to "info"
            - name: FELIX_LOGSEVERITYSCREEN
              value: "info"
            # Set Calico startup logging to "error"
            - name: CALICO_STARTUP_LOGLEVEL
              value: "error"
            # Enable or disable usage report
            - name: FELIX_USAGEREPORTINGENABLED
              value: "False"
            # Set MTU for tunnel device used if ipip is enabled
            - name: FELIX_CHAININSERTMODE
              value: "Insert"
            - name: FELIX_PROMETHEUSMETRICSENABLED
              value: "False"
            - name: FELIX_PROMETHEUSMETRICSPORT
              value: "9091"
            - name: FELIX_PROMETHEUSGOMETRICSENABLED
              value: "True"
            - name: FELIX_PROMETHEUSPROCESSMETRICSENABLED
              value: "True"
            - name: NODEIP
              valueFrom:
                fieldRef:
                  fieldPath: status.hostIP
            - name: IP_AUTODETECTION_METHOD
              value: "can-reach=$(NODEIP)"
            - name: IP
              value: "autodetect"
            - name: NODENAME
              valueFrom:
                fieldRef:
                  fieldPath: spec.nodeName
            - name: FELIX_HEALTHENABLED
              value: "true"
            - name: FELIX_IGNORELOOSERPF
              value: "False"
            - name: CALICO_MANAGE_CNI
              value: "true"
          securityContext:
            privileged: true
          resources:
            limits:
              cpu: 300m
              memory: 500M
            requests:
              cpu: 150m
              memory: 64M
          livenessProbe:
            exec:
              command:
              - /bin/calico-node
              - -felix-live
              - -bird-live
            periodSeconds: 10
            initialDelaySeconds: 10
            timeoutSeconds: 10
            failureThreshold: 6
          readinessProbe:
            exec:
              command:
              - /bin/calico-node
              - -bird-ready
              - -felix-ready
            periodSeconds: 10
            timeoutSeconds: 10
            failureThreshold: 6
          volumeMounts:
            - mountPath: /lib/modules
              name: lib-modules
              readOnly: true
            - mountPath: /var/run/calico
              name: var-run-calico
              readOnly: false
            - mountPath: /var/lib/calico
              name: var-lib-calico
              readOnly: false
            - name: xtables-lock
              mountPath: /run/xtables.lock
              readOnly: false
            # For maintaining CNI plugin API credentials.
            - mountPath: /host/etc/cni/net.d
              name: cni-net-dir
              readOnly: false
            - name: policysync
              mountPath: /var/run/nodeagent
            - name: cni-log-dir
              mountPath: /var/log/calico/cni
              readOnly: true
      volumes:
        # Used by calico/node.
        - name: lib-modules
          hostPath:
            path: /lib/modules
        - name: var-run-calico
          hostPath:
            path: /var/run/calico
        - name: var-lib-calico
          hostPath:
            path: /var/lib/calico
        # Used to install CNI.
        - name: cni-net-dir
          hostPath:
            path: /etc/cni/net.d
        - name: cni-bin-dir
          hostPath:
            path: /opt/cni/bin
        # Mount the global iptables lock file, used by calico/node
        - name: xtables-lock
          hostPath:
            path: /run/xtables.lock
            type: FileOrCreate
        # Mount in the directory for host-local IPAM allocations. This is
        # used when upgrading from host-local to calico-ipam, and can be removed
        # if not using the upgrade-ipam init container.
        - name: host-local-net-dir
          hostPath:
            path: /var/lib/cni/networks
        # Used to access CNI logs.
        - name: cni-log-dir
          hostPath:
            path: /var/log/calico/cni
        # Used to create per-pod Unix Domain Sockets
        - name: policysync
          hostPath:
            type: DirectoryOrCreate
            path: /var/run/nodeagent
        # Used to install Flex Volume Driver
        - name: flexvol-driver-host
          hostPath:
            type: DirectoryOrCreate
            path: "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds"
  updateStrategy:
    rollingUpdate:
      maxUnavailable: 20%
    type: RollingUpdate
    
#  cat calico-kube-controllers.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: calico-kube-controllers
  namespace: kube-system
  labels:
    k8s-app: calico-kube-controllers
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      k8s-app: calico-kube-controllers
  template:
    metadata:
      name: calico-kube-controllers
      namespace: kube-system
      labels:
        k8s-app: calico-kube-controllers
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      hostNetwork: true
      serviceAccountName: calico-kube-controllers
      tolerations:
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
        - key: node-role.kubernetes.io/control-plane
          effect: NoSchedule
      priorityClassName: system-cluster-critical
      containers:
        - name: calico-kube-controllers
          image: registry.local.cloud:5000/calico/kube-controllers:v3.20.3
          imagePullPolicy: IfNotPresent
          resources:
            limits:
              cpu: 1000m
              memory: 256M
            requests:
              cpu: 30m
              memory: 64M
          livenessProbe:
            exec:
              command:
              - /usr/bin/check-status
              - -l
            periodSeconds: 10
            initialDelaySeconds: 10
            failureThreshold: 6
          readinessProbe:
            exec:
              command:
              - /usr/bin/check-status
              - -r
            periodSeconds: 10
          env:
            - name: ENABLED_CONTROLLERS
              value: node
            - name: DATASTORE_TYPE
              value: kubernetes
              
## cni 설정 정보 확인
# ls -al /etc/cni/net.d
total 20
drwxr-xr-x 2 kube root 4096 Aug 26 11:36 ./
drwxr-xr-x 3 kube root 4096 Aug 26 11:08 ../
-rw-r--r-- 1 root root  713 Aug 26 11:36 10-calico.conflist
-rw------- 1 root root 2850 Aug 29 11:59 calico-kubeconfig
-rw-r--r-- 1 root root  715 Aug 26 11:32 calico.conflist.template

# cat 10-calico.conflist
{
  "name": "cni0",
  "cniVersion":"0.3.1",
  "plugins":[
    {
      "datastore_type": "kubernetes",
      "nodename": "playcekube-worker01",
      "type": "calico",
      "log_level": "info",
      "log_file_path": "/var/log/calico/cni/cni.log",
      "ipam": {
        "type": "calico-ipam",
        "assign_ipv4": "true",
        "ipv4_pools": ["10.233.64.0/18"]
      },
      "policy": {
        "type": "k8s"
      },
      "kubernetes": {
        "kubeconfig": "/etc/cni/net.d/calico-kubeconfig"
      }
    },
    {
      "type":"portmap",
      "capabilities": {
        "portMappings": true
      }
    },
    {
      "type":"bandwidth",
      "capabilities": {
        "bandwidth": true
      }
    }
  ]
}

Control-Plane Node의  /etc/kubernetes 의 경로에 있는 파일들을 확인해보면, calico-config의 config map 내용과 calico-config.yml 이 같고,  calico-node 파드와 calico-node.yml 이 같으며, calico-kube-controllers 파드와 calico-kube-controllers.yml이 같다는 것을 알 수 있습니다. yaml 파일들을 이용해 calico가 구성 되는 것으로 보이는군요. 

 나머지 calico-cr.yml, calico-crb.yml, calico-kube-cr.yml, calico-kube-crb.yml 는 Calico에서 사용되는 ClusterRole과 ClusterRoleBinding 입니다. calico-kube-sa.yml, calico-node-sa.yml는 ServiceAccount입니다. Calico 에서 사용하는 모든 설정파일이 Control-plane의 /etc/kubernetes의 경로에 다 있네요.

 Node에서 확인 가능한 다른 경로로는 /etc/cni 의 경로가 있는데요. 여기는 Container Runtime이 구성될때 사용하게 되는 calico 설정이라고 보시면 됩니다. 인증서와 Template가 있고, 이를 이용해 10-calico.conflist 를 작성하여 사용하게 됩니다. 

 Calico 운영 정보 확인 

### ipam 에 할당된 IP Address 정보 확인
#  calicoctl ipam show --show-blocks
+----------+-----------------+-----------+------------+--------------+
| GROUPING |      CIDR       | IPS TOTAL | IPS IN USE |   IPS FREE   |
+----------+-----------------+-----------+------------+--------------+
| IP Pool  | 10.233.64.0/18  |     16384 | 25 (0%)    | 16359 (100%) |
| Block    | 10.233.106.0/24 |       256 | 9 (4%)     | 247 (96%)    |
| Block    | 10.233.113.0/24 |       256 | 2 (1%)     | 254 (99%)    |
| Block    | 10.233.77.0/24  |       256 | 2 (1%)     | 254 (99%)    |
| Block    | 10.233.88.0/24  |       256 | 3 (1%)     | 253 (99%)    |
| Block    | 10.233.99.0/24  |       256 | 9 (4%)     | 247 (96%)    |
+----------+-----------------+-----------+------------+--------------+

 설정 등을 확인하고, Calico가 IP Address를 정상적으로 사용중 인지 확인하기 위해서는 ipam 정보를 확인 해보면 되겠습니다. 10.233.64.0/18 에서 각 노드별로 자동 할당된 24bit(subnet 255.255.255.0, 256 hosts)의 네트워크와 IP Address의 사용량을 확인 할 수 있습니다.
한 노드당 24bit를 사용할 수 있다면, kube-system에서 사용하거나, Service등의 여유를 제외한다면, 150에서 200개의 IP Address를 Pod에서 사용 할 수 있게 됩니다. (kubelet에 설정되어있는 기본 Pod수는 110개)

 Log는 ‘/var/log/calico/cni’의 경로와 ‘/var/log/pods/kube-system_calico-node*’ 의 경로에 cni로그와 calico-node, flexvol-driver, install-cni, upgrade-ipam의 로그가 적제되고 있습니다. 로그의 종류가 상당히 다양합니다. 

 왜 이렇게 많은 로그의 종류가 있을까요. 우선 Control-plane과 Calico-node 크게 두 부분으로 나뉘게 될거고, Calico-node의 image를 보게 된다면,  cni, pod2daemon-flexvol, node 가 생성됩니다. 여기에 ipam에 대한 로그가 생성됩니다. 

 Calico는 봐야할 정보가 정말 많은 것 같습니다. 설정은 간단하지만 작용이 매우 복잡하기 때문이겠죠. 그렇다면 container에서 기동 된 이후에 어떻게 작동 하는지 확인해 보겠습니다. 

 Calico Node 정보 확인 

### Felix 확인 
# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.233.0.1:443 rr
  -> 10.222.0.84:6443             Masq    1      2          0
  -> 10.222.0.158:6443            Masq    1      0          0
  -> 10.222.0.165:6443            Masq    1      2          0
TCP  10.233.0.3:53 rr
  -> 10.233.88.4:53               Masq    1      0          0
  -> 10.233.113.2:53              Masq    1      0          0
TCP  10.233.0.3:9153 rr
  -> 10.233.88.4:9153             Masq    1      0          0
  -> 10.233.113.2:9153            Masq    1      0          0
TCP  10.233.2.41:80 rr
  -> 10.233.99.12:80              Masq    1      0          0
  -> 10.233.106.23:80             Masq    1      0          0
TCP  10.233.2.41:443 rr
  -> 10.233.99.12:444             Masq    1      0          0
  -> 10.233.106.23:444            Masq    1      0          0
TCP  10.233.6.194:443 rr
  -> 10.233.99.15:10250           Masq    1      0          0
TCP  10.233.8.79:6379 rr
  -> 10.233.99.13:6379            Masq    1      0          0
  -> 10.233.106.16:6379           Masq    1      0          0
  -> 10.233.106.17:6379           Masq    1      0          0
TCP  10.233.9.197:80 rr
  -> 10.233.106.21:3000           Masq    1      0          0
TCP  10.233.17.208:80 rr
  -> 10.233.106.20:4180           Masq    1      0          0
TCP  10.233.17.208:44180 rr
  -> 10.233.106.20:44180          Masq    1      0          0
TCP  10.233.18.86:9090 rr
  -> 10.233.106.22:9090           Masq    1      0          0
TCP  10.233.22.239:443 rr
  -> 10.233.77.2:4443             Masq    1      2          0
TCP  10.233.25.169:80 rr
  -> 10.233.99.18:8080            Masq    1      0          0
TCP  10.233.25.169:443 rr
  -> 10.233.99.18:8443            Masq    1      0          0
TCP  10.233.31.233:9100 rr
  -> 10.222.0.15:9100             Masq    1      0          0
  -> 10.222.0.84:9100             Masq    1      0          0
  -> 10.222.0.123:9100            Masq    1      0          0
  -> 10.222.0.158:9100            Masq    1      0          0
  -> 10.222.0.165:9100            Masq    1      0          0
TCP  10.233.37.77:6379 rr
  -> 10.233.106.18:6379           Masq    1      0          0
TCP  10.233.48.81:5432 rr
  -> 10.233.99.14:5432            Masq    1      0          0
TCP  10.233.55.99:8080 rr
  -> 10.233.99.17:8080            Masq    1      0          0
TCP  10.233.60.245:9093 rr
  -> 10.233.99.16:9093            Masq    1      0          0
TCP  10.233.63.123:443 rr
  -> 10.233.99.19:8443            Masq    1      0          0
  -> 10.233.106.19:8443           Masq    1      0          0
UDP  10.233.0.3:53 rr
  -> 10.233.88.4:53               Masq    1      0          0
  -> 10.233.113.2:53              Masq    1      0          0

# ip r
default via 10.0.0.1 dev ens4 proto dhcp src 10.0.0.11 metric 100
default via 10.1.1.254 dev ens3 proto dhcp src 10.1.1.11 metric 100
10.0.0.0/16 dev ens4 proto kernel scope link src 10.0.0.11 metric 100
10.0.0.1 dev ens4 proto dhcp scope link src 10.0.0.11 metric 100
10.0.0.10 dev ens4 proto dhcp scope link src 10.0.0.11 metric 100
blackhole 10.233.77.0/24 proto bird
10.233.77.2 dev calie347534bfe4 scope link
10.233.88.0/24 via 10.0.0.12 dev tunl0 proto bird onlink
10.233.99.0/24 via 10.0.0.21 dev tunl0 proto bird onlink
10.233.106.0/24 via 10.0.0.22 dev tunl0 proto bird onlink
10.233.113.0/24 via 10.0.0.12 dev tunl0 proto bird onlink
169.254.169.254 via 10.0.0.10 dev ens4 proto dhcp src 10.0.0.11 metric 100
169.254.169.254 via 10.1.1.110 dev ens3 proto dhcp src 10.1.1.11 metric 100
10.1.1.0/16 dev ens3 proto kernel scope link src 10.1.1.11 metric 100
10.1.1.1 dev ens3 proto dhcp scope link src 10.1.1.11 metric 100
10.1.1.10 dev ens3 proto dhcp scope link src 10.1.1.11 metric 100
10.1.1.110 dev ens3 proto dhcp scope link src 10.1.1.11 metric 100

# ip -c route | grep bird
blackhole 10.233.77.0/24 proto bird
10.233.88.0/24 via 10.0.0.13 dev tunl0 proto bird onlink
10.233.99.0/24 via 10.0.0.21 dev tunl0 proto bird onlink
10.233.106.0/24 via 10.0.0.22 dev tunl0 proto bird onlink
10.233.113.0/24 via 10.0.0.12 dev tunl0 proto bird onlink

# ip -c route | grep cali
10.233.99.12 dev cali529aed0cdfd scope link
10.233.99.13 dev calia1a4ce1fd14 scope link
10.233.99.14 dev cali0bf64d8a013 scope link
10.233.99.15 dev cali1b77e6bb67a scope link
10.233.99.16 dev cali7c21de47b2f scope link
10.233.99.17 dev calie8b6d9446c8 scope link
10.233.99.18 dev cali8442edcb221 scope link
10.233.99.19 dev cali7029cbd2dfb scope link
10.233.99.20 dev cali6b516219e5f scope link
10.233.99.21 dev cali3a199d39f75 scope link
10.233.99.22 dev cali39d0067cf12 scope link

## calico interface 확인 
# calicoctl get workloadendpoints -a | grep cali529aed0cdfd
cattle-system   cattle-cluster-agent-679697c475-9l4p6                       playcekube-worker01   10.233.99.12/32    cali529aed0cdfd

## calico interface 네트워크 확인 
# tcpdump -i cali529aed0cdfd -nn
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on cali529aed0cdfd, link-type EN10MB (Ethernet), snapshot length 262144 bytes
15:20:59.286266 IP 10.233.0.1.443 > 10.233.99.12.36640: Flags [P.], seq 2348022798:2348023587, ack 3076275329, win 9683, options [nop,nop,TS val 2811409034 ecr 611887874], length 789
15:20:59.286300 IP 10.233.99.12.36640 > 10.233.0.1.443: Flags [.], ack 789, win 10245, options [nop,nop,TS val 611888182 ecr 2811409034], length 0
15:20:59.286350 IP 10.233.0.1.443 > 10.233.99.12.36640: Flags [P.], seq 789:1352, ack 1, win 9683, options [nop,nop,TS val 2811409034 ecr 611887874], length 563
15:20:59.286378 IP 10.233.99.12.36640 > 10.233.0.1.443: Flags [.], ack 1352, win 10241, options [nop,nop,TS val 611888182 ecr 2811409034], length 0
:
:

 확인 부분이 조금 길어지네요. bird는 BGP를 생성하여 Routing Table을 생성하고 있습니다.
Felix는 모든 노드의 endpoint 와 etcd의 정보를 읽고 쓰고, iptables/ipvsadm 등을 컨트롤합니다.
confd는 etcd에 bird의 구성을 업데이트 하거나 변경을 감시합니다. 


 ipvsadm으로는 Service를 통해서 Pod까지의 경로를 알 수 있습니다. ip route로는 현재 노드에서 타 노드로 가는 라우팅과 현재 노드에서 구성되어 있는 Pod의 endpoint IP Address를 알 수 있습니다.

현재 노드에 할당된 내부 IP Address 대역은 ip -c route | grep bird 로 확인이 가능합니다. calico가 연동되는 calico interface 를 확인 하려면 p -c route | grep calico 로 확인이 가능합니다.

이때 보이는 dev 이름 cali* 를 이용해서 Pod를 확인하려면 calicoctl get workloadendpoints -a | grep cali* 로 확인이 가능합니다. 그리고 tcpdump -i cali* 를 이용한다면 Pod의 네트워크 사용량을 확인 할 수 있습니다. Pod가 있는 서버에서 확인한다면, 네트워크상의 이상 유무를 바로 알 수 있겠습니다.

해당 정보는 모든 Node가 동일하게 구성됩니다. 만약 1개의 Node가 구성이 다르다면, Calico구성 혹은 Node의 네트워크에 단절이 생긴 것으로 판단해도 되겠습니다.

 Calico Architecture 

 Calico를 최초의 아키텍처에서 우리가 확인한 정보들을 확인하면서 본다면 아래의 그림처럼 구성됩니다. 


Calico 구성
componentDescribe
Felixcalico-node 파드 안에 위치하며, 모든 노드의 endpoint 제공
K8s ETCD 정보를 읽음
라우팅 테이블 생성
kube-proxy가 iptables 모드인 경우, iptables 컨트롤
kube-proxy가 ipvs 모드인 경우, ipvs 컨트롤
Bird다른 노드에 있는 BGP 데몬들과 라우팅 정보 교환.
TCP 179를 이용해서 mesh 형태로 연결
ConfdCalico 데이터 저장소의 구성 변경을 감시하고 BIRD의 구성 파일을 업데이트하는 데몬

결론

Playce Kube의 구축시 생성되는 CNI(calico network)를 확인 하는 방법과 서비스 흐름을 찾는 방법을 알아보았습니다.

Kubernetes 에서 구축되는 Pod 네트워크는 상당히 중요합니다. 각 Node에 산발되어 있는 모든 Pod를 각 Node에 할당된 24bit 내의 가상 네트워크를 모든 서버에 등록해야 하고, 라우팅을 해야 합니다.

여기에 각 Pod의 생성과 제거에 따른 IP Address의 관리, 그리고 생성된 Pod에 외부에서 오는 서비스 흐름을 생성해 추가로 라우팅을 해줘야하는 매우 복잡한 형태 입니다.

단순한 서버 네트워크로는 운영하기에 너무나도 어려운 부분으로 보입니다만, Playce Kube에서 사용하는 Calico Network는 구축과 구성을 운영자의 부담없이 운영될 수 있게 구축 되어있습니다.

하지만 가상네트워크를 다루는 만큼 실제 운영 구조는 복잡하게 되어있죠. Kubernetes의 구성에 중요하지 않은 부분은 없겠지만, 어느 일정 이상의 서비스를 운영하게 된다면 네트워크 상태를 알지 못하면 낭패를 당할 수 있습니다.

Node에서 Pod를 찾아가거나 서비스를 추적하면서 많이 연습하고 구조를 OSI 7 Layer에 맞추어 생각한다면 조금더 친근한 Interface가 될 것 같습니다.

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


참고사이트

kubectl 명령어

Kubernetes Components

Kubernetes CNI

Calico

쿠버네티스-위키백과

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 *