8주차 - Cillium CNI

1. 목적성

  • Cllium을 배포하고 기본정보를 확인해봅니다.

  • Cillium의 장점을 몸소 느껴보고 eBPF 기반 네트워킹의 장점과 동작원리를 알아봅니다.

  • Iptables의 단점을 확인하고, eBPF의 장점을 비교해봅니다.

2. BPF 란?

  • 리눅스 네트워크 스택은 복잡하고, 변경에 대한 시간이 많이 걸리고 레이어를 건너뛰기 어렵다는 단점이 존재 -> 이를 위해서 BPF 가 극복하기 위한 수단으로 등장함

  • BPF (Berkley Packet Filter)는 커널 수준의 패킷 캡처 및 필터링을 위해 만들어 졌으며, 다양한 훅을 통해 네트워크 스택에 쉽게 접근이 가능합니다.

2.b eBPF란?

  • 기존의 BPF의 확장버전으로, 커널의 거의 모든 부분을 관찰 할 수 있습니다.

  • eBPF의 특정 영역에서 다음과 같은 영역들에서 활용할 수 있습니다.

    • Networking: 네트워크 트래픽의 필터링 혹은 라우팅을 할 수 있습니다.

    • Observabililty: eBPF가 데이터를 수집하고, 분석할 수 있게 합니다.

    • Tracing: 커널과 사용자 공간의 프로세스의 Stack Traces를 기로가할 수 있습니다.

    • Security: 커널 시스템 호출을 가로채서 모니터링 할 수 있습니다. 보안 위협을 방지할 수 있습니다.

2.c Iptables의 한계점

  • k8s의 kube-proxy는 Iptables Rules를 통해 서비스와 로드 밸런싱을 구현한다.

  • 대부분의 CNI 플러그인 - 네트워크 정책을 위해 iptables를 사용

  • 업데이트시 모든 규칙을 다시 생성 및 업데이트

  • 규칙을 사용하는데에서도 모든 규칙을 확인하게 됩니다.

  • 새 ip에 대해서 사용할 때, 규칙을 추가해야합니다.

  • iptable의 기하급수적 증가를 경험할 수 밖에 없습니다.

이에 따라, eBPF가 필연적으로 등장하게 됩니다.

2.d eBPF 구동 원리

  • eBPF 프로그램들의 상태값을 저장하는 Maps 를 가지고, 사용자 공간의 프로그램을 커널의 동적으로 로드하고 사용합니다.

3. Cillium CNI 란?

  • Cillium CNI는 eBPF를 활용해서 k8s 환경에서 많은 레이어를 통한 통신보다는 하나의 계층만 거치면서 통신을 수행하게 됩니다.

  • 기존의 iptables 기반의 동작에 대해 성능을 유의미 하게 향상시킵니다.

  • 네트워크 정책 관리 및 세부적인 정책을 정의할 수 있습니다.

  • 호스트간 라우팅 + pod에서의 라우팅을 동작할 때 생기는 많은 iptables에 대한 오버헤드없이 통신을 수행하면서 성능에 이점이 생깁니다.\

3.a Cillium 아키텍처

  • Cilium Agent : 데몬셋으로 실행, K8S API 설정으로 부터 '네트워크 설정, 네트워크 정책, 서비스 부하분산, 모니터링' 등을 수행하며, eBPF 프로그램을 관리한다.

  • Cilium Client (CLI) : Cilium 커멘드툴, eBPF maps 에 직접 접속하여 상태를 확인할 수 있다.

  • Cilium Operator : K8S 클러스터에 대한 한 번씩 처리해야 하는 작업을 관리.

4. Cillium 배포

// Cloud stack 배포 yaml 파일
# YAML 파일 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/kans/kans-8w.yaml

// 실습환경 배포 확인
aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text

// KUBE PROXY 없는것을 확인
// kc get pod -A

# 
helm repo add cilium https://helm.cilium.io/
helm repo update

#
helm install cilium cilium/cilium --version 1.16.3 --namespace kube-system \
--set k8sServiceHost=192.168.10.10 --set k8sServicePort=6443 --set debug.enabled=true \
--set rollOutCiliumPods=true --set routingMode=native --set autoDirectNodeRoutes=true \
--set bpf.masquerade=true --set bpf.hostRouting=true --set endpointRoutes.enabled=true \
--set ipam.mode=kubernetes --set k8s.requireIPv4PodCIDR=true --set kubeProxyReplacement=true \
--set ipv4NativeRoutingCIDR=192.168.0.0/16 --set installNoConntrackIptablesRules=true \
--set hubble.ui.enabled=true --set hubble.relay.enabled=true --set prometheus.enabled=true --set operator.prometheus.enabled=true --set hubble.metrics.enableOpenMetrics=true \
--set hubble.metrics.enabled="{dns:query;ignoreAAAA,drop,tcp,flow,port-distribution,icmp,httpV2:exemplars=true;labelsContext=source_ip\,source_namespace\,source_workload\,destination_ip\,destination_namespace\,destination_workload\,traffic_direction}" \
--set operator.replicas=1

## 주요 파라미터 설명
--set debug.enabled=true # cilium 파드에 로그 레벨을 debug 설정
--set autoDirectNodeRoutes=true # 동일 대역 내의 노드들 끼리는 상대 노드의 podCIDR 대역의 라우팅이 자동으로 설정
--set endpointRoutes.enabled=true # 호스트에 endpoint(파드)별 개별 라우팅 설정
--set hubble.relay.enabled=true --set hubble.ui.enabled=true # hubble 활성화
--set ipam.mode=kubernetes --set k8s.requireIPv4PodCIDR=true # k8s IPAM 활용
--set kubeProxyReplacement=true # kube-proxy 없이 (최대한) 대처할수 있수 있게
--set ipv4NativeRoutingCIDR=192.168.0.0/16 # 해당 대역과 통신 시 IP Masq 하지 않음, 보통 사내망 대역을 지정
--set operator.replicas=1 # cilium-operator 파드 기본 1개
--set enableIPv4Masquerade=true --set bpf.masquerade=true # 파드를 위한 Masquerade , 추가로 Masquerade 을 BPF 로 처리 >> enableIPv4Masquerade=true 인 상태에서 추가로 bpf.masquerade=true 적용이 가능

# 설정 및 확인
ip -c addr
kubectl get node,pod,svc -A -owide
iptables -t nat -S
iptables -t filter -S
iptables -t raw -S
iptables -t mangle -S
conntrack -L


helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values --set installNoConntrackIptablesRules=true

# 확인: 기존 raw 에 아래 rule 추가 확인
iptables -t raw -S | grep notrack
-A CILIUM_OUTPUT_raw -d 192.168.0.0/16 -m comment --comment "cilium: NOTRACK for pod traffic" -j CT --notrack
  • Iptables에 entry가 거의 없는것을 확인할 수 있습니다.

  • Cillium 설치를 확인합니다.

# Cilium CLI 설치
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-${CLI_ARCH}.tar.gz /usr/local/bin
rm cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}


# 확인
cilium status --wait
cilium config view

# Configure the eBPF-based ip-masq-agent
# https://docs.cilium.io/en/stable/network/concepts/masquerading/
helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values --set ipMasqAgent.enabled=true

export CILIUMPOD0=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-s  -o jsonpath='{.items[0].metadata.name}')
alias c0="kubectl exec -it $CILIUMPOD0 -n kube-system -c cilium-agent -- cilium"
c0 status --verbose | grep Masquerading
  • Cillium을 설치한 이후에 CLI로 Daemon들을 확인합니다.

5. Cillium 기본 정보

# cilium 파드 이름
export CILIUMPOD0=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-s  -o jsonpath='{.items[0].metadata.name}')
export CILIUMPOD1=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-w1 -o jsonpath='{.items[0].metadata.name}')
export CILIUMPOD2=$(kubectl get -l k8s-app=cilium pods -n kube-system --field-selector spec.nodeName=k8s-w2 -o jsonpath='{.items[0].metadata.name}')

# 단축키(alias) 지정
alias c0="kubectl exec -it $CILIUMPOD0 -n kube-system -c cilium-agent -- cilium"
alias c1="kubectl exec -it $CILIUMPOD1 -n kube-system -c cilium-agent -- cilium"
alias c2="kubectl exec -it $CILIUMPOD2 -n kube-system -c cilium-agent -- cilium"

alias c0bpf="kubectl exec -it $CILIUMPOD0 -n kube-system -c cilium-agent -- bpftool"
alias c1bpf="kubectl exec -it $CILIUMPOD1 -n kube-system -c cilium-agent -- bpftool"
alias c2bpf="kubectl exec -it $CILIUMPOD2 -n kube-system -c cilium-agent -- bpftool"

# Hubble UI 웹 접속
kubectl patch -n kube-system svc hubble-ui -p '{"spec": {"type": "NodePort"}}'
HubbleUiNodePort=$(kubectl get svc -n kube-system hubble-ui -o jsonpath={.spec.ports[0].nodePort})
echo -e "Hubble UI URL = http://$(curl -s ipinfo.io/ip):$HubbleUiNodePort"

# 자주 사용 명령
helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values --set
kubetail -n kube-system -l k8s-app=cilium --since 12h
kubetail -n kube-system -l k8s-app=cilium-envoy --since 12h
# cilium 파드 확인
kubectl get pod -n kube-system -l k8s-app=cilium -owide

# cilium 파드 재시작
kubectl -n kube-system rollout restart ds/cilium
혹은
kubectl delete pod -n kube-system -l k8s-app=cilium

# cilium 설정 정보 확인
cilium config view

# cilium 파드의 cilium 상태 확인
c0 status --verbose

# cilium 엔드포인트 확인
kubectl get ciliumendpoints -A
c0 endpoint list
c0 bpf endpoint list
c0 map get cilium_lxc
c0 ip list

# Manage the IPCache mappings for IP/CIDR <-> Identity
c0 bpf ipcache list

# Service/NAT List 확인
c0 service list
c0 bpf lb list
c0 bpf lb list --revnat
c0 bpf nat list

# List all open BPF maps
c0 map list
c0 map list --verbose

# List contents of a policy BPF map : Dump all policy maps
c0 bpf policy get --all
c0 bpf policy get --all -n

# cilium monitor
c0 monitor -v
c0 monitor -v --type l7

Last updated