안녕하세요. Playce Cloud팀 이성림입니다.

쿠버네티스 파드 네트워크에 이은 두 번째 칼리코입니다.

  

칼리코 소개

쿠버네티스 네트워크는 CNI(Container Network Interface) 표준을 지키는 네트워크 플러그인이 필요합니다. CNI 표준을 지키는 솔루션은 Calico 이외에도 다양한 선택지가 있지만 저희 팀에서 설계/제안 할 때 주로 선택하는 것이 Calico이기 때문에 주제로 선정하였습니다. 네트워크 플러그인에서 지원하는 항목이나 특성, 성능에 따라서 다른 플러그인을 선택하여 사용할 수 있습니다.

CNI 참고 사이트)

https://kubernetes.io/ko/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/

https://github.com/containernetworking/cni

 

쿠버네티스 네트워크 플러그인은 표준 CNI를 따라야 한다고 하는데 아래와 같은 요구사항이 있다고 합니다. 쿠버네티스를 경험해 보신 분이라면 당연히 되어야 할 기능으로 생각되지 않으신가요?

1. veth 페어 생성 및 컨테이너 네트워크 인터페이스와 연결
2. Pod 네트워크 대역 확인 후 IP 설정
3. CNI 설정 파일 작성
4. IP 설정 및 관리
5. 컨테이너 내 기본 라우팅 정보 삽입 (default route rule)
6. 동료 노드들에게 IP 라우팅 정보 전달(advertising the routes)
7. 호스트 서버에 라우팅 정보 삽입
8. 네트워크 정책에 따라 트래픽 처리
...
출처 - https://coffeewhale.com/packet-network2

 

칼리코 개발 회사인 Tigera 홈페이지에서 칼리코 아키텍처를 확인할 수 있습니다.

Calico Architecture (출처 https://www.tigera.io/tigera-products/calico/)

네트워크 플러그인은 노드/파드 통신을 원할하게 해주는 역할을 하기 때문에 쿠버네티스 노드에 네트워크 화살표만 그려져 있는 것을 볼 수 있습니다. 간단한 그림이 실제로는 어떻게 구성이 되어져 있는지 확인해보도록 하겠습니다.

설명에 설명하는 쿠버네티스에서 사용하는 칼리코 버전은 v3.21.2입니다.

root@sung-ubuntu01:~/tmp# calicoctl version
Client Version:    v3.21.2
Git commit:        17461419
Cluster Version:   v3.21.2
Cluster Type:      kubespray,bgp,kubeadm,kdd,k8s

  calicoctl 명령어로 모든 노드가 메쉬 형태로 연결되어 있는 것을 확인 할 수 있습니다.

root@sung-ubuntu01:~/tmp# calicoctl node status 
Calico process is running.
IPv4 BGP status
+-----------------+-------------------+-------+----------+-------------+
|  PEER ADDRESS   |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+-----------------+-------------------+-------+----------+-------------+
| 192.168.110.101 | node-to-node mesh | up    | 02:45:04 | Established |
| 192.168.110.103 | node-to-node mesh | up    | 02:40:50 | Established |
| 192.168.110.104 | node-to-node mesh | up    | 02:41:00 | Established |
| 192.168.110.102 | node-to-node mesh | up    | 02:44:42 | Established |
+-----------------+-------------------+-------+----------+-------------+
root@sung-ubuntu04:~# calicoctl node status
Calico process is running.
IPv4 BGP status
+-----------------+-------------------+-------+----------+-------------+
|  PEER ADDRESS   |     PEER TYPE     | STATE |  SINCE   |    INFO     |
+-----------------+-------------------+-------+----------+-------------+
| 192.168.110.100 | node-to-node mesh | up    | 02:40:49 | Established |
| 192.168.110.101 | node-to-node mesh | up    | 02:45:02 | Established |
| 192.168.110.104 | node-to-node mesh | up    | 02:40:59 | Established |
| 192.168.110.102 | node-to-node mesh | up    | 02:44:42 | Established |
+-----------------+-------------------+-------+----------+-------------+

 마스터 노드에서 wokrloadEndpoint를 조회하면, 생성된 파드 정보와 노드 위치, 인터페이스까지 확인 할 수 있습니다.

*master 서버에서만 출력
# 생성된 파드에 대한 위치, 정보 확인
root@sung-ubuntu01:~/tmp# calicoctl get workloadEndpoint
WORKLOAD           NODE            NETWORKS         INTERFACE
multi-container    sung-ubuntu05   10.233.78.3/32   calib4cfe5eb958
multi-container2   sung-ubuntu04   10.233.99.2/32   calia85a668c715
ubuntu-test        sung-ubuntu04   10.233.99.1/32   calie3df4d89b13

  BGP 피어링은 179번 포트를 사용하며, 아래 BGP 그림을 참고하시면 이해하기가 쉽습니다.

root@k8s-master01:~# netstat -antlp | grep 179
tcp    0    0 0.0.0.0:179    0.0.0.0:*    LISTEN    831313/bird
tcp    0    0 192.168.110.111:179     192.168.110.115:54063   ESTABLISHED 831313/bird
tcp    0    0 192.168.110.111:179     192.168.110.112:40507   ESTABLISHED 831313/bird
tcp    0    0 192.168.110.111:179     192.168.110.113:52189   ESTABLISHED 831313/bird
tcp    0    0 192.168.110.111:179     192.168.110.114:51323   ESTABLISHED 831313/bird

 

 Q. 위 상태에서 multi-container2 파드를 삭제하면 sung-ubuntu04 노드의 인터페이스는 어떻게 변할까요?

-> 칼리코 workloadEndpoint에서도 삭제 되겠지만 노드에서 생성된 해당 파드와 연결된 인터페이스도 삭제 됩니다. ifconfig 명령어로 확인 시 calib4cfe5eb958 인터페이스가 삭제되게 됩니다.

 

BGP(Border Gateway Protocol)

BGP는 기업의 사내망과 인터넷, 국가 간 통신 방법에 비유 할 수 있습니다. AS(Autonomous System)은 각 Zone을 의미하며, 쿠버네티스에서는 해당 내용을 각 노드 내 파드 통신과 노드 간의 통신으로 적용하여 설명 할 수 있습니다.

AS 간 통신은 eBGP라고 하며, AS 내 통신은 iBGP라고 합니다.

 

칼리코 구성확인 및 Data-Path 확인

💡 리눅스 네임스페이스
1. 리눅스 시스템은 초기 구동 시 하나의 단일 네임스페이스를 갖는다.
2. 파일 시스템, 프로세스ID, 사용자ID, 네트워크 인터페이스 등과 같은 모든 시스템 자원은 단일 네임스페이스에 속한다.
3. 네임스페이스를 추가로 만들고 리소스를 구성할 수 있다.
4. 프로세스를 실행하면 프로세스는 네임스페이스 중 하나에서만 실행되며 동일 네임스페이스 내 리소스만 볼수 있다.
5. 여러 종류의 네임스페이스가 존재하므로 프로세스는 하나의 네임스페이스에만 속하지 않고 각 종류의 네임스페이스에 속한다.
6. 네임스페이스는 마운트(mnt), 프로세스(pid), 네트워크(net), 프로세스간 통신(ipc), UTS, 사용자ID(user)가 있다.

 Q. 컨테이너가 리눅스의 네임스페이스 격리 기술을 활용 한다던데.. 어떻게 확인할 수 있을까요?

#네트워크 네임스페이스 확인
root@sung-ubuntu04:~# lsns -t net
NS TYPE NPROCS    PID USER    NETNSID NSFS                           COMMAND
4026531992 net     160      1 root unassigned /run/docker/netns/default      /sbin/init
4026532314 net       3 313510 root          0 /run/docker/netns/6c1ef9da93ed /pause
4026532393 net       7 474316 root          1 /run/docker/netns/6698a621349f /pause

*컨테이너는 네트워크 네임스페이스로 네트워크를 분리하기 때문에 2개의 파드가 서로 다른 네트워크 네임스페이스(0,1)을 가지는 것을 확인할 수 있습니다.

#Pause Container가 부모 프로세스입니다.
root@sung-ubuntu04:~# ps -ef | grep 313510
root      313510  313479  0 12:35 ?        00:00:00 /pause

 칼리코 인터페이스 dump를 통해 실제 트래픽이 이동하는 것을 확인해 보겠습니다.


#4번 노드에서 cali 인터페이스 확인
root@sung-ubuntu04:~# ifconfig -a
calia85a668c715: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1480
        inet6 fe80::ecee:eeff:feee:eeee  prefixlen 64  scopeid 0x20<link>
        ether ee:ee:ee:ee:ee:ee  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5  bytes 446 (446.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
calie3df4d89b13: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1480
        inet6 fe80::ecee:eeff:feee:eeee  prefixlen 64  scopeid 0x20<link>
        ether ee:ee:ee:ee:ee:ee  txqueuelen 0  (Ethernet)
        RX packets 3747  bytes 254298 (254.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5769  bytes 24076756 (24.0 MB)


#calia85a668c715 인터페이스 tcpdump 확인
root@sung-ubuntu04:~# VETH1=calia85a668c715
root@sung-ubuntu04:~# tcpdump -i $VETH1 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on calia85a668c715, link-type EN10MB (Ethernet), capture size 262144 bytes
..대기중


#마스터 노드에서 4번 노드 POD에 ping 테스트(다른 세션)
root@sung-ubuntu01:~/tmp# kubectl get pod -o wide
NAME               READY   STATUS    RESTARTS   AGE     IP            NODE            NOMINATED NODE   READINESS GATES
multi-container    2/2     Running   0          164m    10.233.78.3   sung-ubuntu05   <none>           <none>
multi-container2   2/2     Running   0          69m     10.233.99.2   sung-ubuntu04   <none>           <none>
ubuntu-test        1/1     Running   0          3h16m   10.233.99.1   sung-ubuntu04   <none>           <none>


#ping
root@sung-ubuntu01:~/tmp# ping 10.233.99.2
PING 10.233.99.2 (10.233.99.2) 56(84) bytes of data.
64 bytes from 10.233.99.2: icmp_seq=1 ttl=63 time=1.38 ms


#calia85a668c715 인터페이스 tcpdump 확인
root@sung-ubuntu04:~# tcpdump -i $VETH1 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on calia85a668c715, link-type EN10MB (Ethernet), capture size 262144 bytes
16:05:46.144509 IP 10.233.95.0 > 10.233.99.2: ICMP echo request, id 2, seq 1, length 64
16:05:46.145001 IP 10.233.99.2 > 10.233.95.0: ICMP echo reply, id 2, seq 1, length 64
#sung-ubuntu01(10.233.95.0) -> sung-ubuntu04(10.233.99.2)로 ICMP echo request 확인


---


#sung-ubuntu05 노드의 파드에서 ping 테스트
root@sung-ubuntu01:~/tmp# kubectl exec -it multi-container -c ubuntu -- bash
root@multi-container:/# ping 10.233.99.2


root@sung-ubuntu04:~# tcpdump -i $VETH1 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on calia85a668c715, link-type EN10MB (Ethernet), capture size 262144 bytes
16:13:18.856132 IP 10.233.78.3 > 10.233.99.2: ICMP echo request, id 341, seq 1, length 64
16:13:18.856660 IP 10.233.99.2 > 10.233.78.3: ICMP echo reply, id 341, seq 1, length 64
16:13:23.952285 ARP, Request who-has 10.233.99.2 tell 192.168.110.103, length 28
16:13:23.952244 ARP, Request who-has 169.254.1.1 tell 10.233.99.2, length 28
16:13:23.952792 ARP, Reply 169.254.1.1 is-at ee:ee:ee:ee:ee:ee, length 28
16:13:23.952809 ARP, Reply 10.233.99.2 is-at f6:8b:49:61:d0:02, length 28


* 169.254.1.1(link-local address)
169.254.1.1는 IP 주소 관리 대행사가 예약한 예약 IP 주소이며 공용 또는 개인 IP로 할당되지 않습니다. 
예약된 IP는 일반적으로 소프트웨어, 개인 네트워크, 호스트, 서브넷, 문서, 변환, 멀티 캐스트, 브로드 캐스트, 로컬 통신, 루프백, 릴레이, 링크, 매핑, 테스트 및 향후 사용과 같은 특수 목적으로 사용됩니다. 
출처 - https://ko.ipshu.com/ipv4/169.254.1.1

 쿠버네티스에서 사용하는 칼리코 Pool과 해당 Pool이 어떤 모드를 사용하는지도 확인 할 수 있습니다.

구축 후 모드 변경이 가능하며, calico 홈페이지에서 자세한 방법을 확인 할 수 있습니다.

#Calico NAT 정책 확인 (true)
root@sung-ubuntu01:~/tmp# 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()


#워커 노드에서 iptables nat 확인
root@sung-ubuntu04:~# iptables -n -t nat --list cali-nat-outgoing
Chain cali-nat-outgoing (1 references)
target     prot opt source               destination
MASQUERADE  all  --  0.0.0.0/0            0.0.0.0/0            /* cali:flqWnvo8yq4ULQLa */ match-set cali40masq-ipam-pools src ! match-set cali40all-ipam-pools dst random-fully
=> cali-nat-outgoing 정책으로 외부로 나가는 패킷은 모두 MASQUERADE하여 처리됨 (=외부로 나가는 트래픽은 MASQURADE 정책을 통해 나갈 수 있음)


*IP Masquerade
 - NAT 기술 안에 속한 기술로 가면이라는 의미
 - NAT와 다르게 주소변환만 하는 것이 아닌 포트번호까지 포트포워딩 시켜주는 기능을 가지고 있음

 - SNAT(Source NAT)와 같다고 함.

 

칼리코 모드

칼리코 네트워크 방식은 Overlay 방식과 Overlay를 사용하지 않는 방식(Direct)로 구분 할 수 있으며, 쿠버네티스 배포 툴인 kubespray release-2.19 부터 기본 옵션이 ipip에서 vxlan으로 변경되었습니다.

1. Direct 방식
  - Pod 통신 패킷이 출발지 라우팅 정보를 보고 목적지 노드로 원본 패킷 그대로 전달
  - 성능적으로 가장 우수
2. Overlay 방식 (터널링)
  - Pod의 네트워크 정보를 노드에서 Encapsulation(캡슐화)하여 목적지 노드로 전달
  - IP 기반의 터널링 방식으로 파드의 패킷 전달
  - 각 노드 패킷에 대한 Encapsulation / Decapsulation 과정 실행
  2.1. IPIP 모드
     → IP-in-IP라고 불리우는 Overlay 방식으로, Calico의 기본 모드
     → Pod의 네트워크 패킷의 기존 IP헤더 앞에 IP헤더를 하나 더 덧붙여 통신하는 방식
     → 다른 노드간 Pod 통신은 tunl0 인터페이스를 통해 IP 헤더에 감싸져서 상대 노드로 도달 후        tunl0 인터페이스에서 Outer 헤더를 제거하고 내부의 파드와 통신
  2.2 VXLAN 모드
     → POD간 통신이 노드 구간에 VXLAN Encapsultation을 통해 이루어 짐

 

Q. 노드의 칼리코 인터페이스의 mtu는 몇으로 설정되어 있나요?

 

칼리코 구성요소

Calico 모듈과 그 기능들에 대해서 정리해 보겠습니다.

아래 표는 calico 홈페이지에 정리된 내용을 일부 번역/정리하였습니다.

💡 Calico 구성요소
 - The `calico/node` container is deployed to every node (on Kubernetes, by a DaemonSet), and runs three internal daemons:
Felix(필릭스) 
 - the Calico daemon that runs on every node and provides endpoints.
 - calico-node 파드 안에 위치하며, 모든 노드의 endpoint 제공
    - K8s ETCD 정보를 읽음
    - 라우팅 테이블 생성
    - kube-proxy가 iptables 모드인 경우, iptables 컨트롤
    - kube-proxy가 ipvs 모드인 경우, ipvs 컨트롤 |
BIRD(버드) 
 - the BGP daemon that distributes routing information to other nodes.
 - 다른 노드에 있는 BGP 데몬들과 라우팅 정보 교환. 
 - TCP 179를 이용해서 mesh 형태로 연
confd 
 - a daemon that watches the Calico datastore for config changes and updates 
   BIRD’s config files.
 - Calico 데이터 저장소의 구성 변경을 감시하고 BIRD의 구성 파일을 업데이트하는 데몬
출처 - [https://projectcalico.docs.tigera.io/reference/node/configuration]

 실제로 칼리코는 쿠버네티스에서 어떻게 배포되어 사용되고 있을까요?

#calino-node는 daemonset으로 배포되어있습니다.
root@sung-ubuntu01:/var/lib/cni# kubectl -n kube-system get all | grep cali
pod/calico-kube-controllers-6bc8445c8-kptbp   1/1     Running   48        2d23h
pod/calico-node-ckvhb                  1/1     Running   4 (2d23h ago)    2d23h
pod/calico-node-d2pr7                  1/1     Running   5 (2d23h ago)    2d23h
pod/calico-node-fnmg9                  1/1     Running   5 (2d23h ago)    2d23h
pod/calico-node-gqr27                  1/1     Running   9 (2d23h ago)    2d23h
pod/calico-node-gzrt9                  1/1     Running   8 (2d23h ago)    2d23h
daemonset.apps/calico-node    5   5   5   5   5   kubernetes.io/os=linux  2d23h
deployment.apps/calico-kube-controllers   1/1     1           1           2d23h
replicaset.apps/calico-kube-controllers-6bc8445c8   1       1       1     2d23h

 calico-node 파드를 살펴보겠습니다. 어떤 컨테이너들로 구성되어 있는지, Probe는 어떻게 체크하는지, 기본 리소스는 어떻게 설정되어 있는지 확인해보세요. 시스템에 규모/사용량에 따라서 리소스를 수정해야하는 경우가 있습니다.


root@sung-ubuntu01:~# kubectl -n kube-system describe pod calico-node-ckvhb
Name:                 calico-node-ckvhb
Namespace:            kube-system
Priority:             2000001000
Priority Class Name:  system-node-critical
Node:                 sung-ubuntu01/192.168.110.100
Start Time:           Fri, 26 Aug 2022 11:33:59 +0900
Labels:               controller-revision-hash=bc4df5999
                      k8s-app=calico-node
                      pod-template-generation=1
Annotations:          <none>
Status:               Running
IP:                   192.168.110.100
IPs:
  IP:           192.168.110.100
Controlled By:  DaemonSet/calico-node
Init Containers:
  upgrade-ipam:
    Container ID:  docker://5c0d79f72455a568d8df8242131c7c997200ad6a0612819e76ed731a599f5d18
    Image:         quay.io/calico/cni:v3.21.2
    Image ID:      docker-pullable://quay.io/calico/cni@sha256:7aa6c97fc5f6a6959f8b06bacc12e6f593c68e6e0839e1f454ba0b9523255a79
    Port:          <none>
    Host Port:     <none>
    Command:
      /opt/cni/bin/calico-ipam
      -upgrade
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Fri, 26 Aug 2022 11:34:42 +0900
      Finished:     Fri, 26 Aug 2022 11:34:42 +0900
    Ready:          True
    Restart Count:  0
    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-bhp9z (ro)
  install-cni:
    Container ID:  docker://deaf5d827119ae09e88b6f2dd816e4e7d7b04b5bbe39c67daaf70b268af3f2cd
    Image:         quay.io/calico/cni:v3.21.2
    Image ID:      docker-pullable://quay.io/calico/cni@sha256:7aa6c97fc5f6a6959f8b06bacc12e6f593c68e6e0839e1f454ba0b9523255a79
    Port:          <none>
    Host Port:     <none>
    Command:
      /opt/cni/bin/install
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Fri, 26 Aug 2022 11:35:33 +0900
      Finished:     Fri, 26 Aug 2022 11:36:19 +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-bhp9z (ro)
  flexvol-driver:
    Container ID:   docker://af898ab3c87a361deb668e39cccbcbaa8e8b7cc2bc3779bffcddb25d8b298d23
    Image:          quay.io/calico/pod2daemon-flexvol:v3.21.2
    Image ID:       docker-pullable://quay.io/calico/pod2daemon-flexvol@sha256:2397cea01382233f942edeecc2c205e241aa0a292e2624449df9b6c9381fa1a5
    Port:           <none>
    Host Port:      <none>
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Fri, 26 Aug 2022 11:36:45 +0900
      Finished:     Fri, 26 Aug 2022 11:36:45 +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-bhp9z (ro)
Containers:
  calico-node:
    Container ID:   docker://8f6b34864db9b809b59a8da7e9149979d91bdac10c5477edcd70ebbf593e14d0
    Image:          quay.io/calico/node:v3.21.2
    Image ID:       docker-pullable://quay.io/calico/node@sha256:895a10b9d68d8f724f72e0bd002d435862ce997c85658ce7d4c6407c34bc65ab
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Fri, 26 Aug 2022 11:40:30 +0900
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1
      Started:      Fri, 26 Aug 2022 11:39:13 +0900
      Finished:     Fri, 26 Aug 2022 11:39:31 +0900
    Ready:          True
    Restart Count:  4
    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-bhp9z (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-bhp9z:
    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-node 설정에서 설정 파일을 찾으셨나요? 해당 파일을 찾아보면 실제로 칼리코의 설정을 확인 할 수 있습니다.

root@sung-ubuntu01:/etc/cni/net.d# ll
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
root@sung-ubuntu01:/etc/cni/net.d# cat 10-calico.conflist
{
  "name": "cni0",
  "cniVersion":"0.3.1",
  "plugins":[
    {
      "datastore_type": "kubernetes",
      "nodename": "sung-ubuntu01",
      "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
      }
    }
  ]
}

 

칼리코 노드/파드 인터페이스 이해

칼리코 인터페이스 설명 부분에서 169.254.1.1 아이피가 기억나시나요? 해당 아이피를 특수 목적으로 사용하는 예약 IP 주소라고 설명을 했습니다. 해당 아이피를 link-local address라고 하며, 쿠버네티스 노드 인터페이스와 파드 안의 인터페이스를 이어주는 역할을 합니다.

###
#sung-ubuntu05 노드의 파드에서 ping 테스트
root@sung-ubuntu01:~/tmp# kubectl exec -it multi-container -c ubuntu -- bash
root@multi-container:/# ping 10.233.99.2
root@sung-ubuntu04:~# tcpdump -i $VETH1 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on calia85a668c715, link-type EN10MB (Ethernet), capture size 262144 bytes
16:13:18.856132 IP 10.233.78.3 > 10.233.99.2: ICMP echo request, id 341, seq 1, length 64
16:13:18.856660 IP 10.233.99.2 > 10.233.78.3: ICMP echo reply, id 341, seq 1, length 64
16:13:23.952285 ARP, Request who-has 10.233.99.2 tell 192.168.110.103, length 28
16:13:23.952244 ARP, Request who-has 169.254.1.1 tell 10.233.99.2, length 28
16:13:23.952792 ARP, Reply 169.254.1.1 is-at ee:ee:ee:ee:ee:ee, length 28
16:13:23.952809 ARP, Reply 10.233.99.2 is-at f6:8b:49:61:d0:02, length 28
###
TCP dump 상에서 보였던 낯선 IP 169.254.1.1는 예약 IP 주소이며, link-local address
💡 link-local address
 - 직접 연결된 동일 링크 및 subnet에서 사용하는 주소
 - 링크 로컬 주소는 FE80::/10의 고정된 대역과 interface의 EUI-64 ID의 결합으로 이루어짐
 - 169.254.1.0 ~ 169.254.254.255(IPv4) 범위의 예약된 네트워크 주소

다시 노드의 네트워크 인터페이스를 확인해 보겠습니다. 노드 인터페이스가 파드 인터페이스와 어떻게 연결이 되어있는지 dump내용과 비교해보세요.

root@sung-ubuntu04:~# ifconfig
calia85a668c715: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1480
        inet6 fe80::ecee:eeff:feee:eeee  prefixlen 64  scopeid 0x20<link>
        ether ee:ee:ee:ee:ee:ee  txqueuelen 0  (Ethernet)
        RX packets 75  bytes 6790 (6.7 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 80  bytes 7236 (7.2 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
calie3df4d89b13: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1480
        inet6 fe80::ecee:eeff:feee:eeee  prefixlen 64  scopeid 0x20<link>
        ether ee:ee:ee:ee:ee:ee  txqueuelen 0  (Ethernet)
        RX packets 3747  bytes 254298 (254.2 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5769  bytes 24076756 (24.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
...
#ubuntu 컨테이너 접속
root@sung-ubuntu01:~/tmp# kubectl exec -it multi-container -c ubuntu -- bash
root@multi-container:/# apt install iproute2 -y
root@multi-container:/# ip route
default via 169.254.1.1 dev eth0
169.254.1.1 dev eth0 scope link
=> 169.254.1.1는 파드의 IPv4 link-local Address

 

마지막으로 공식 홈페이지에서 설명하는 칼리코 데이터흐름을 확인해보세요.

길게 설명한 내용이 한 페이지에 정리가 되어있으며, 모든 것이 칼리코에서 자동으로 이루어지기 때문에 흐름만 익히면 문제가 생겼을 경우 해결이 수월 할 것입니다!

https://projectcalico.docs.tigera.io/reference/architecture/data-path

 

 

 

 

이성림
Cloud Engineer

오픈소스컨설팅 Playce Cloud팀 소속으로 폭 넓은 지식과 깊이 있는 지식 모두 포기할 수 없는 이성림입니다. 하나 알았다 싶으면 다시 새로운 두 개가 나오는 세상에서 살아남아 보도록 하겠습니다.

Leave a Reply

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