1. Cilium 이란?
2. XDP란?
3. Cillum 설치
1. Cilium ?
Cilium은 eBPF (Berkeley Packet Filter)를 기반으로 Pod Network 환경 + 보안 을 제공하는 CNI Plugin 입니다
2021년 10월에 CNCF 소속 프로젝트가 되었고,
현재는 Google GKE Data Plane, AWS EKS Anywhere에 Cilium을 기본 CNI로 이용
k8s에서 구체적으로 살펴보면, Cilium이 없는 경우엔 좌측 그림처럼 호스트와 Pod 환경에서 동일한 동작을 수행하면서 오버헤드가 존재하게 되는데, Cilium을 이용하게 되면 기타 중복되는 오버헤드 없이 통신을 수행하게 되면서 성능에 많은 이점이 존재
eBPF (Berkeley Packet Filter)
"효율적인 네트워킹, 가시성, 추적, 보안을 위해 커널을 동적으로 프로그래밍한다."
- BPF(1992년) 를 확장해서 eBPF가 (2014년, Alexei Starovoitov) 가 나왔고, eBPF 를 다양한 영역 (보안, 추적, 네트워킹, 모니터링)에서 활용하기 시작하였습니다.
"eBPF는 커널 소스 코드를 변경하거나 커널 모듈을 로드하지 않고도 리눅스 커널에서 샌드박스된 프로그램을 실행할 수 있는 혁신적인 기술입니다."
2. XDP ?
XDP(eXpress Data Path) : eBPF based fast data-path
XDP(eXpress Data Path)는 네트워크 패킷이 운영체제에 도달하기 전에 빠르게 처리할 수 있게 해주는 Linux 기능입니다. 이렇게 하면 네트워크 성능을 크게 높이고, 데이터를 주고받는 속도(레이턴시)를 줄일 수 있습니다. XDP는 네트워크 트래픽이 많을 때도 효과적으로 처리할 수 있는 방법을 제공하며, 세 가지 방식으로 동작합니다: Native XDP, Offloaded XDP, Generic XDP입니다.
- 테스트 환경 : pktgen - send UDP packet
- 10GBe로 테스트
- 패킷 드랍 결과
- userspace와 15배 속도 차이
Native XDP
Native XDP는 네트워크 카드(NIC)에서 들어오는 패킷을 운영체제로 보내기 전에 네트워크 드라이버 단계에서 바로 처리하는 방식입니다. 이 방식은 패킷이 네트워크 스택에 도달하기 전에 드라이버에서 처리되므로, 매우 빠른 성능을 제공합니다. 대부분의 10Gbps 이상의 네트워크 카드가 이 방식을 지원하며, 패킷이 CPU에 도달하지 않아 성능 저하를 방지하고 레이턴시를 줄일 수 있습니다.
Offloaded XDP
Offloaded XDP는 스마트NIC과 같은 특수 네트워크 카드가 XDP 프로그램을 CPU 대신 직접 실행하는 방식입니다. 이렇게 되면 패킷이 CPU를 거치지 않고 네트워크 카드 자체에서 처리되므로 성능이 더욱 향상됩니다. CPU의 부담을 줄이면서도 네트워크 성능을 극대화할 수 있어, 고성능 네트워크 환경에서 매우 유용합니다.
Generic XDP
Generic XDP는 네트워크 카드에서 XDP를 지원하지 않는 경우에 사용됩니다. 이 방식에서는 XDP 프로그램이 운영체제의 커널에서 소프트웨어적으로 패킷을 처리합니다. 성능은 Native XDP나 Offloaded XDP에 비해 떨어지지만, 네트워크 드라이버를 수정하지 않고도 XDP를 사용할 수 있다는 장점이 있습니다.
Cilium 설치 실습
# 모니터링
watch -d kubectl get node,pod -A -owide
#
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
kubectl get crd
kubectl get ciliumnodes # cilium_host 인터페이스의 IP 확인 : CILIUMINTERNALIP
kubectl get ciliumendpoints -A
kubectl get cm -n kube-system cilium-config -o json | jq
kubetail -n kube-system -l k8s-app=cilium --since 1h
kubetail -n kube-system -l k8s-app=cilium-envoy --since 1h
# Native XDP 지원 NIC 확인 : https://docs.cilium.io/en/stable/bpf/progtypes/#xdp-drivers
ethtool -i ens5
driver: ena
version: 6.8.0-1015-aws
...
# https://docs.cilium.io/en/stable/operations/performance/tuning/#bypass-iptables-connection-tracking
watch -d kubectl get pod -A # 모니터링
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
-A CILIUM_OUTPUT_raw -s 192.168.0.0/16 -m comment --comment "cilium: NOTRACK for pod traffic" -j CT --notrack
...
conntrack -F
conntrack -L
conntrack -L |grep -v 2379
옵션 | 설명 |
helm install cilium cilium/cilium | cilium이라는 이름으로 Helm 차트를 설치하고, Cilium 차트를 사용합니다. |
--version 1.16.3 | Cilium의 버전을 1.16.3으로 설치합니다. |
--namespace kube-system | Cilium을 kube-system 네임스페이스에 설치합니다. |
--set k8sServiceHost=192.168.10.10 | Kubernetes API 서버의 IP 주소를 192.168.10.10으로 설정합니다. |
--set k8sServicePort=6443 | Kubernetes API 서버의 포트를 6443으로 설정합니다. |
--set debug.enabled=true | 디버그 모드를 활성화하여 상세한 로그를 출력합니다. |
--set rollOutCiliumPods=true | 기존 Cilium 파드를 자동으로 롤링 업데이트하여 재시작합니다. |
--set routingMode=native | Cilium의 네이티브 라우팅 모드를 사용하여 직접 패킷을 라우팅합니다. |
--set autoDirectNodeRoutes=true | 노드 간 자동으로 직접 라우팅을 설정하여 성능을 향상시킵니다. |
--set bpf.masquerade=true | eBPF를 사용하여 NAT(Masquerade) 기능을 처리합니다. |
--set bpf.hostRouting=true | eBPF 기반의 호스트 라우팅을 활성화하여 호스트 네트워크 트래픽을 처리합니다. |
--set endpointRoutes.enabled=true | 각 파드에 고유한 라우팅 경로를 설정하여 세밀한 트래픽 제어가 가능합니다. |
--set ipam.mode=kubernetes | Kubernetes의 IP 주소 관리(IPAM)를 사용합니다. |
--set k8s.requireIPv4PodCIDR=true | Kubernetes 클러스터에서 IPv4 CIDR 사용을 요구합니다. |
--set kubeProxyReplacement=true | Cilium이 kube-proxy를 대체하여 eBPF 기반의 서비스 라우팅 및 로드 밸런싱을 처리합니다. |
--set ipv4NativeRoutingCIDR=192.168.0.0/16 | IPv4 네이티브 라우팅을 위한 CIDR 블록을 192.168.0.0/16으로 지정합니다. |
--set installNoConntrackIptablesRules=true | Cilium이 iptables의 Conntrack 규칙을 설치하지 않도록 설정합니다. |
--set hubble.ui.enabled=true | Hubble UI(웹 기반 네트워크 모니터링 도구)를 활성화합니다. |
--set hubble.relay.enabled=true | Hubble Relay를 활성화하여 여러 Hubble 에이전트의 데이터를 수집할 수 있습니다. |
--set prometheus.enabled=true | Prometheus를 활성화하여 Cilium의 메트릭을 수집합니다. |
--set operator.prometheus.enabled=true | Cilium Operator에서 Prometheus 메트릭을 활성화합니다. |
--set hubble.metrics.enableOpenMetrics=true | OpenMetrics 표준을 사용하여 Prometheus 호환 메트릭을 수집합니다. |
--set hubble.metrics.enabled="{...}" | Hubble에서 DNS, TCP, ICMP, HTTP 등 다양한 네트워크 메트릭 수집을 활성화합니다. |
--set operator.replicas=1 | Cilium Operator의 복제본 수를 1개로 설정하여 리소스를 절약합니다. |
# Native XDP 지원 NIC 확인
# iptables 확인
(⎈|CiliumLab:N/A) root@k8s-s:~# iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N CILIUM_OUTPUT_nat
-N CILIUM_POST_nat
-N CILIUM_PRE_nat
-N KUBE-KUBELET-CANARY
-A PREROUTING -m comment --comment "cilium-feeder: CILIUM_PRE_nat" -j CILIUM_PRE_nat
-A OUTPUT -m comment --comment "cilium-feeder: CILIUM_OUTPUT_nat" -j CILIUM_OUTPUT_nat
-A POSTROUTING -m comment --comment "cilium-feeder: CILIUM_POST_nat" -j CILIUM_POST_nat
-P PREROUTING ACCEPT | PREROUTING 체인의 기본 정책을 ACCEPT로 설정합니다. 즉, 이 체인을 통과하는 패킷은 기본적으로 허용됩니다. |
-P INPUT ACCEPT | INPUT 체인의 기본 정책을 ACCEPT로 설정합니다. 즉, 이 체인을 통과하는 패킷은 기본적으로 허용됩니다. |
-P OUTPUT ACCEPT | OUTPUT 체인의 기본 정책을 ACCEPT로 설정합니다. 즉, 이 체인을 통과하는 패킷은 기본적으로 허용됩니다. |
-P POSTROUTING ACCEPT | POSTROUTING 체인의 기본 정책을 ACCEPT로 설정합니다. 즉, 이 체인을 통과하는 패킷은 기본적으로 허용됩니다. |
-N CILIUM_OUTPUT_nat | 새로운 체인(CILIUM_OUTPUT_nat)을 생성합니다. 이 체인은 Cilium에 의해 관리되는 NAT 규칙을 포함합니다. |
-N CILIUM_POST_nat | 새로운 체인(CILIUM_POST_nat)을 생성합니다. 이 체인은 Cilium에 의해 관리되는 POSTROUTING NAT 규칙을 포함합니다. |
-N CILIUM_PRE_nat | 새로운 체인(CILIUM_PRE_nat)을 생성합니다. 이 체인은 Cilium에 의해 관리되는 PREROUTING NAT 규칙을 포함합니다. |
-A PREROUTING -m comment --comment "cilium-feeder: CILIUM_PRE_nat" -j CILIUM_PRE_nat | PREROUTING 체인에 대한 규칙을 추가하여 CILIUM_PRE_nat 체인으로 패킷을 전달합니다. 이 패킷은 Cilium의 NAT 처리를 위해 지정됩니다. |
-A OUTPUT -m comment --comment "cilium-feeder: CILIUM_OUTPUT_nat" -j CILIUM_OUTPUT_nat | OUTPUT 체인에 대한 규칙을 추가하여 CILIUM_OUTPUT_nat 체인으로 패킷을 전달합니다. Cilium의 NAT 처리를 위해 지정됩니다. |
-A POSTROUTING -m comment --comment "cilium-feeder: CILIUM_POST_nat" -j CILIUM_POST_nat | POSTROUTING 체인에 대한 규칙을 추가하여 CILIUM_POST_nat 체인으로 패킷을 전달합니다. Cilium의 NAT 처리를 위해 지정됩니다. |
# 네트워크 구조 확인
- 위에서 확인한 NIC을 보면 lxcx와 cilium_net, cilium_host 등을 확인할 수 있습니다.
- 노드 IP들을 확인해 보면 위에서 추가된 cilium_host@cilium_net IP와 동일합니다.
# 네트워크 인터페이스 정보 확인
ip -br -c link
ip -br -c addr
--------------------------------------------
# cilium_net 과 cilium_host 는 veth peer 관계이며, cilium_host 는 파드의 GW IP 주소로 지정되며 32bit 이다
ip -c addr show cilium_net ; ip -c addr show cilium_host
5: cilium_net@cilium_host: <BROADCAST,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 36:88:bf:c9:5c:6c brd ff:ff:ff:ff:ff:ff
...
6: cilium_host@cilium_net: <BROADCAST,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 4e:6a:8e:44:85:61 brd ff:ff:ff:ff:ff:ff
inet 172.16.1.254/32 scope link cilium_host
...
# proxy arp 는 disable(0) 상태이며, 파드와 연결된 lxc 도 모두 0 이다
# 파드의 32bit ip의 gw 가 각각 연결된 veth 인터페이스의 mac 으로 cilium_host 의 IP/MAC 응답을 처리한다, 어떻게 동작이 되는걸까요? >> eBPF program!!!
cat /proc/sys/net/ipv4/conf/cilium_net/proxy_arp
0
cat /proc/sys/net/ipv4/conf/cilium_host/proxy_arp
0
# lxc_health 인터페이스는 veth 로 cilium(NET NS 0, 호스트와 다름)과 veth pair 이다 - 링크
# cilium 인터페이스에 파드 IP가 할당되어 있으며, cilium-health-responder 로 동작한다
lsns -t net
Hubble UI
- Hubble 소개 : 통신 및 서비스와 네트워킹 인프라의 동작에 대한 심층적인 가시성을 완전히 투명한 방식으로 제공하는 관찰성을 제공 - Blog
- Hubble is a fully distributed networking and security observability platform. → 네트워크/보안 모니터링
- It is built on top of Cilium and eBPF to enable deep visibility into the communication and behavior of services as well as the networking infrastructure in a completely transparent manner. without requiring the application to change in any way. → 애플리케이션의 코드 수정 등 추가 설정 없이 동작
- containerized workloads as well as more traditional workloads such as virtual machines and standard Linux processes. → VM/서버도 모니터링 가능
- By leveraging Linux eBPF, Cilium retains the ability to transparently insert security visibility + enforcement, but does so in a way that is based on service / pod / container identity (in contrast to IP address identification in traditional systems) and can filter on application-layer (e.g. HTTP). → 전통적인 IP 기반은 모니터링/통제가 아니라 서비스/파드/ID 기반으로 모니터링/통제를 제공
- 기본적으로 Hubble API는 Cilium 에이전트가 실행되는 개별 노드의 범위 내에서 작동합니다. 이는 네트워크 통찰력을 로컬 Cilium 에이전트가 관찰한 트래픽으로 제한합니다. Hubble CLI( hubble)를 사용하여 로컬 Unix Domain Socket을 통해 제공된 Hubble API를 쿼리할 수 있습니다. Hubble CLI 바이너리는 기본적으로 Cilium 에이전트 포드에 설치됩니다.
- Hubble Relay를 배포하면 전체 클러스터 또는 ClusterMesh 시나리오의 여러 클러스터에 대한 네트워크 가시성이 제공됩니다. 이 모드에서 Hubble 데이터는 Hubble CLI( hubble)를 Hubble Relay 서비스로 지정하거나 Hubble UI를 통해 액세스할 수 있습니다. Hubble UI는 L3/L4 및 L7 계층에서 서비스 종속성 그래프를 자동으로 검색할 수 있는 웹 인터페이스로, 사용자 친화적인 시각화 및 서비스 맵으로서의 데이터 흐름 필터링을 허용합니다.
Hubble UI 설치
- 설치
# 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"
## Service NodePort 생성 후 아래 정보 확인!
iptables -t nat -S
conntrack -L
conntrack -L |grep -v 2379
# Install 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 observe --pod netpod
# hubble observe --namespace galaxy --http-method POST --http-path /v1/request-landing
# hubble observe --pod deathstar --protocol http
# hubble observe --pod deathstar --verdict DROPPED
# 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
- UI 확인
'컨테이너 > 쿠버네티스 네트워크' 카테고리의 다른 글
[KANS] 쿠버네티스 네트워크 (17) AWS EKS: VPC CNI (0) | 2024.11.01 |
---|---|
[KANS] 쿠버네티스 네트워크 (16) Cilium - pod통신, service 통신 (0) | 2024.10.26 |
[KANS] 쿠버네티스 네트워크 (14) Service Mesh (istio) : Traffic Management (0) | 2024.10.19 |
[KANS] 쿠버네티스 네트워크 (13) Service Mesh : istio (0) | 2024.10.17 |
[KANS] 쿠버네티스 네트워크 (12) Gateway API (0) | 2024.10.12 |