새소식

Kubernetes

[Study 8주차] 쿠버네티스 Cilium CNI 개요

  • -

CoudNet@ 팀의 가시다님께서 리딩하시는 KANS Study (Kubernetes Advanced Networking Study) 8주차 스터디 내용 정리

 

이번 주차에서는 Cilium CNIeBPF 에 대해서 상세하게 공부를 했습니다.

 

 

 

1. eBPF

 

1.1. 개요

 

eBPF 에 대해 알기 위해서는 전통적인 네트워크 스택에 대해서 이해해야 합니다.

 

출처 : https://bit.ly/3EiLsU3

 

Linux 커널은 여러 추상적인 계층으로 나뉘어져 있어 복잡합니다.

전통적인 네트워크에서는 상호 네트워크 통신에 iptables 를 사용하게 되는데,

쿠버네티스 환경으로 가게되면서 iptable 이 굉장히 많이 필요하게 되었고 그에따라 iptables 의 비효율성이 발생하게 되었습니다.

 

 

출처 :  https://bit.ly/3EiLsU3

 

BPF (Berkeley Packet Filter) 는 원래 Unix 시스템에서 네트워크 패킷을 효율적으로 캡처하고 필터링하기 위해 개발된 기술입니다.

 

BPF 주요 기능

 

1. 패킷 필터링

네트워크 인터페이스로 들어오거나 나가는 패킷 중에서 특정 조건에 맞는 패킷만을 선택하여 처리
불필요한 데이터를 필터링해 성능 최적화 가능

 

2. 저수준 접근 방식

네트워크 드라이버와 같은 저수준에서 동작하여 보다 효율적

 

3. 확장성과 보안성

커널이 사용자 정의 필터를 안전하게 실행할 수 있게 함

 

BPF 가 발전된 것이 eBPF (Extended Berkeley Packet Filter) 입니다.

 

 

1.2. 전통적인 iptables 의 문제점

 

iptables 은 새로운 IP 나 포트를 매칭할 때마다 규칙을 추가하는 등의 변경을 가해야 합니다.
또한, iptables 는 패킷이 iptables 규칙에 일치할 때까지 모든 규칙을 순차적으로 평가하는데 이러한 규칙이 많아 질수록 성능이 떨어진다는 단점이 있습니다.

예를 들어, 1500개의 테이블을 가지고 있는데 1400번째에 해당하는 패킷이 들어온다면 iptables 1번부터 1399번까지 모두 규칙을 평가하고 1400번째에 규칙이 맞다면 해당하는 쪽으로 트래픽을 흘려보내는 것입니다.

 

위와 같은 문제로 인해 높은 트래픽 상황이나 iptable 규칙에 많은 변경이 필요한 시스템에서는 성능이 저하될 수 있습니다.

 

BPF 에서는 iptables 를 사용하지 않고 linux 커널에서 패킷을 처리하기 때문에 위와 같은 단점이 모두 해소됩니다.
또한 커널단에서 패킷을 처리하기 때문에, 성능이 월등히 우수해 최근에 각광받고 있는 기술입니다.

 

앞서 말했듯이, eBPF 는 BPF 가 발전한 모습이며 리눅스 커널 내에 자유롭게 프로그래밍하여 적용 할 수 있는 장점이 있습니다.

 

eBPF 기능

 

1. 동적 프로그램 로딩

eBPF는 커널 모듈을 재컴파일하거나 재부팅할 필요 없이,

사용자 공간에서 커널로 코드를 동적으로 로드하여 커널의 동작을 확장하거나 맞춤화할 수 있습니다.

네트워크 필터링, 추적, 성능 모니터링 등에 필요한 코드를 커널 내부에 안전하게 주입할 수 있습니다.

 

2. 고성능

eBPF는 네트워크 패킷과 같은 데이터 흐름을 커널에서 직접 처리하여, 사용자 공간과 커널 공간 간의 불필요한 데이터 전송을 줄입니다.

 

3. 안전성과 샌드박스 환경

eBPF 프로그램은 커널로 로드되기 전에 엄격한 검증 과정을 거치며, 특정 조건을 벗어나지 못하도록 제한되어 있습니다.

이러한 제한 덕분에 eBPF는 커널을 안정적으로 유지하면서도 추가 기능을 구현할 수 있습니다.

 

4. 다양한 용도

eBPF는 네트워크 패킷 필터링 외에도 파일 시스템 이벤트, 프로세스 및 메모리 관리 등 다양한 커널 이벤트를 추적할 수 있어, 성능 모니터링, 보안 분석, 네트워크 정책 관리 등 여러 분야에 유용하게 활용됩니다.



2. Cilium

 

2.1. 개요

 

CiliumeBPF 를 기반으로 Pod Network 환경과 보안을 제공하는 CNI 플러그인입니다.

 

Cilium eBPF 는 추가적인 설정 변경 없이 리눅스 커널을 자유롭게 프로그래밍하여 동작이 가능하도록 합니다.
또한, iptables 를 거의 사용하지 않기 때문에 네트워크 성능을 최적화할 수 있습니다. (kube-proxy 대체)

 

 

Cilium Architecture

출처 :  https://github.com/cilium/cilium

 

1. Cilium Agent

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

 

2. Cilium Client (CLI)

- Cilium 커맨드 도구, eBPF maps 에 직접 접속하여 상태 확인 가능

 

3. Cilium Operator

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

 

4. Hubble

- 네트워크와 보안 모니터링 플랫폼 역할을 하여, 'Server, Relay, Client, Graphical UI' 로 구성되어 있다.

 

5. Data Store

- Cilium Agent 간의 상태를 저장하고 전파하는 데이터 저장소, 2가지 종류 중 선택(K8S CRDs, Key-Value Store)

 

 

 

2.2. 실습 환경 구성

 

Cilium 실습은 AWS 환경에서 진행했습니다.

 

서버 환경 구성

 

# CFN 스택 다운로드
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/kans/kans-8w.yaml

# CloudFormation 스택 배포
STACK_NAME=kimalarm-stack
AWS_REGION=ap-northeast-2
KEY_NAME=kimalarmkey

aws cloudformation deploy \
  --template-file kans-8w.yaml \
  --stack-name ${STACK_NAME} \
  --parameter-overrides KeyName=${KEY_NAME} SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 \
  --region ${AWS_REGION}

 

Cilium 환경 구성을 위해 kube-proxy 가 없는 형태로 K8S 클러스터가 구성이 되었습니다.
때문에 Node 의 상태가 NotReady 인 것을 알 수 있습니다.

 

Cilium 배포

 

# Cilium Helm Repo 등록
helm repo add cilium https://helm.cilium.io/
helm repo update

# Cilium Helm 설치
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

 

## 주요 파라미터 설명
# 1. cilium 파드에 로그 레벨을 debug 설정
--set debug.enabled=true

# 2. 동일 대역 내의 노드들 끼리는 상대 노드의 podCIDR 대역의 라우팅이 자동으로 설정
--set autoDirectNodeRoutes=true 

# 3. 호스트에 endpoint(파드)별 개별 라우팅 설정
--set endpointRoutes.enabled=true 

# 4. hubble 활성화
--set hubble.relay.enabled=true 
--set hubble.ui.enabled=true 

# 5. k8s IPAM 활용
--set ipam.mode=kubernetes
--set k8s.requireIPv4PodCIDR=true 

# 6. kube-proxy 없이 (최대한) 대처할수 있수 있게
--set kubeProxyReplacement=true 

# 7. 해당 대역과 통신 시 IP Masq 하지 않음, 보통 사내망 대역을 지정
--set ipv4NativeRoutingCIDR=192.168.0.0/16

# 8. cilium-operator 파드 기본 1개
--set operator.replicas=1 

# 9. 파드를 위한 Masquerade , 추가로 Masquerade 을 BPF 로 처리
# >> enableIPv4Masquerade=true 인 상태에서 추가로 bpf.masquerade=true 적용이 가능
--set enableIPv4Masquerade=true
--set bpf.masquerade=true

 

설치 후, Node 상태가 Ready 가 된 것과 CoreDNS 에 IP 가 할당 된 것을 알 수 있습니다.

 

# iptables 규칙 확인
iptables -t nat -S

 

이전 kube-proxy 를 사용할 때보다 훨씬 간결한 iptables 규칙을 볼 수 있습니다.

 

 

2.3. Cilium CLI 설치

 

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 상태 확인
cilium status --wait

 

 

IP Masquerade 활성화


클러스터를 떠나는 모든 트래픽의 소스 IP 주소를 노드의 IPv4 주소로 자동으로 위장
노드의 IP 주소는 이미 네트워크에서 라우팅 가능하기 때문

# IP Masquerade 활성화
helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values --set ipMasqAgent.enabled=true

# 설정 확인
cilium config view | grep -i masq

 

 

 

2.4. Cilium 변수 및 정보 확인

 

실습 중 Cilium 에 대한 명령어를 빠르게 입력하기 위해 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"

 

Hubble UI 접근 화면

 

Cilium 정보 확인

 

아래와 같은 다양한 명령어를 통해 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

 

Cilium 에서 iptables 대신 사용하는 service list 규칙에 대해서 확인할 수 있습니다.

 

Cilium Network Interface 확인

 

cilium_net 과 cilium_host 는 veth peer 관계로 구성되어 있습니다.

 

ip -br -c addr

 

 

출처:  http://arthurchiao.art/blog/ctrip-network-arch-evolution/

 

 

 

3. Hubble

 

3.1. 개요

 

출처:  https://cilium.io/blog/2019/11/19/announcing-hubble

 

 

HubbleCilium 이 사용하는 네트워크 가시성 및 모니터링 도구로,

eBPF를 기반으로 Kubernetes 네트워크 트래픽과 보안 상태를 실시간으로 관찰할 수 있도록 해줍니다.

 

 

3.2. Hubble 구성 요소

 

1. Hubble Agent
각 워커 노드에서 실행
동일한 노드에서 실행되는 Cilium 에이전트와 상호 작용하고 flow 쿼리 API와 메트릭 제공

 

2. Hubble Storage
허블의 저장 계층은 노드당 고정된 수의 flow 를 저장할 수 있는 메모리 내 저장소로 구성
문제 해결 목적으로 flow 의 간략한 기록을 제공

 

3. Hubble CLI
Hubble CLI는 특정 노드에서 실행되는 Hubble 에이전트의 flow 쿼리 API 에 연결하고 서버 측 필터링을 사용하여 메모리 내 스토리지에 저장된 flow 를 쿼리

 

4. Hubble UI
Hubble UI는 flow 쿼리 API를 사용하여 관찰된 플로우를 기반으로 그래픽 서비스 통신 맵 제공
서비스 맵은 서비스 종속성을 표시하고 레이어 3-7에서 네트워크 및 API 호출 시각화 가능

 

 

3.3. Hubble 접근 및 사용

 

# UI 파드 정보 확인
kubectl get pod -n kube-system -l k8s-app=hubble-ui -o wide

# 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"


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

# Hubble API Access : localhost TCP 4245 Relay 를 통해 접근, observe 를 통해서 flow 쿼리 확인 가능!
cilium hubble port-forward &

# CLI 로 Hubble API 상태 확인
hubble status

# query the flow API and look for flows
hubble observe

 

Hubble 을 통해서 Cilium 네트워크 흐름을 확인할 수 있습니다.

 


 

이번 글에서는 Cilium 설치와 구성요소에 대해서 알아보았습니다.

다음 글부터는 Cilium 동작 방식에 대해서 알아보겠습니다.

Contents

포스팅 주소를 복사했습니다