배포
배포방식은 공식문서에 자세하게 나와있으며 다양한 방식으로 배포할 수 있습니다.
helm repo add cilium https://helm.cilium.io/
helm repo update
실습 배포 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
정말 다양한 환경변수 값을 가지고 있으며 대략적으로 중요한 것들을 소개해 보겠습니다.
자세한 내용은 공식문서에서 참조하시기 바랍니다.
debug.enabled=true | cilium 파드에 로그 레벨을 debug 설정 |
autoDirectNodeRoutes=true | 동일 대역 내의 노드들 끼리는 상대 노드의 podCIDR 대역의 라우팅이 자동으로 설정 |
endpointRoutes.enabled=true |
호스트에 endpoint(파드)별 개별 라우팅 설정 |
hubble.relay.enabled=true hubble.ui.enabled=true |
hubble 활성화 |
ipam.mode=kubernetes k8s.requireIPv4PodCIDR=true |
k8s IPAM 활용 |
kubeProxyReplacement=true | kube-proxy 없이 (최대한) 사용 |
ipv4NativeRoutingCIDR=192.168.0.0/16 | 해당 대역과 통신 시 IP Masq 하지 않음 |
operator.replicas=1 | cilium-operator 파드 기본 1개 |
enableIPv4Masquerade=true bpf.masquerade=true |
파드를 위한 Masquerade , 추가로 Masquerade 을 BPF 로 처리 |
ip테이블 조회
iptable을 직접적으로 이용하지 않고 BPF를 이용하기 때문에 iptable이 매우 작은 것을 볼 수 있다.
iptables -t filter -S
conntrack 조회
conntrack -L |grep -v 2379
contract table 역시 크게 별도로 많지않으며, notrack 옵션은 해당 트래픽은 추적하지 않는다고 생각하면 된다.
2379는 etcd와 정기적으로 통신하는 포트이므로 해당 포트는 제외하고 조회해본다.
cilium CLI 설치
cilium CLI를 통해서 CLI에서도 손쉽게 cilium을 사용해 볼 수 있다. 상태조회나 설정값 확인, 설정 변경 등을 바로바로 진행할 수 있어 매우 편하다. 설치 방법은 공식문서에서 아주 자세히 나와있다.
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 명령어를 통해서 상태를 조회해볼 수 있다.
cilium status --wait
config view 명령으로 설정값에 대해서 자세하게 확인할 수 있다. 정말 많은 설정 값이 있어서 필터해서 보는 것을 추천한다.
cilium config view
운영되는 각 cilium의 상태를 보려면 해당 컨테이너에 들어가서 status 명령어를 통해서 모듈의 상태까지도 체크할 수 있다.
kubectl exec -it <your-cilium-pod-name> -n kube-system -c cilium-agent -- cilium status --verbose
Hubble
Hubble은 통신 및 서비스와 네트워킹 인프라의 동작에 대해 관찰가능성을 제공하는 기능이다. 깔끔하게 UI로 매우 잘 만들어져있다. 네트워크 뿐 아니라 보안적인 모니터링도 같이 제공한다. 기본적으로 Cilium 에이전트가 실행되는 개별 노드 범위 내에서 동작하기 때문에 로컬 Cilium 에이전트가 관찰한 트래픽으로 한정된다.
또한 Hubble도 자체 CLI가 Cilium 에이전트 파드에 기본적으로 설치되기 때문에 CLI를 사용하여 로컬 Unix Domain Socket을 통해서 Hubble API를 쿼리한다. 애플리케이션 코드에 추가적인 설정 없이도 바로 사용할 수 있기 때문에 설치도 매우 쉽다.
eBPF 기반의 플러그인을 도입할때 가장 주의해야할 것
보안툴이나 운영툴이랑 충돌이 날 수 있다. eBPF를 사용해버리면 보안프로그램에서 지나가야하는 트래픽들이 우회하는 경우가 발생해서 로그가 수집안될 수도 있다.
Hubble Relay를 배포하면 전체 클러스터나 Service Mesh 시나리오의 여러 클러스터에 대한 네트워크 가시성도 제공된다.
Hubble UI 확인해보기
Hubble이 별도로 설치되어 이기 때문에 손 쉽게 바로 찾아서 들어가면 된다. 우리는 NodePort 방식으로 외부에서 접근하였다.
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 CLI를 이용하기 위해서는 Client 설치가 필요하다. 공식문서에서 설치 가이드를 보고 설치하면 된다.
현재 실습간 서버는 amd64 아키텍처를 사용하고 있기 때문에 이렇게 설치하였다. 본인의 아키텍처에 맞게 설치하기 바란다.
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}
CLI로 확인하기
Hubble API로 접근하기 위해 포트포워딩이 필요하다.
cilium hubble port-forward &
만약 포트포워딩이 안되있다면 다음과 같은 오류가 난다.
failed to connect to 'localhost:4245': connection error: desc = "transport: error while dialing: dial tcp 127.0.0.1:4245: connect: connection refused"
일반적으로 localhost TCP 4245 Relay를 통해서 접근하며, observe를 통해서 flow 쿼리를 확인할 수 있다.
모니터링
CLI를 통해서 트래픽 모니터링을 하기 위해서는 다음 명령어를 사용한다.
hubble observe
쉽게 프토로콜 (L7까지 가능하다)이나 pod간의 트래픽도 확인할 수 있다.
자가 테스트
자가 테스트도 가능한데 다음 명령어로 진행할 수 있다. 스스로 내부 간 통신이나 외부 통신을 저 명령어 하나만으로 자체적으로 체크한다. 다만 시간이 오래걸리므로 여유가 있을 때 실행해보기 바란다.
cilium connectivity test
진단이 완료되면 결과를 잘 살펴보고 리소스를 삭제하기 바란다.
kubectl delete ns cilium-test-Y
노드 간 파드 통신
Pod 통신을 확인하기 위해서 control-plane에는 netpod를 그리고 worker-node1과 worker-node2에는 whoami 컨테이너로 구성된 webpod를 각각 두었다.
Pod통신을 확인하기 위해 ping과 curl로 조회해 보면 새로 고침도 필요없이 실시간으로 트래픽이 추적되고, 놀라운것은 그림도 그려준다.
참고로 8080은 컨테이너에 없는 포트인데, 호출했으므로 그림상에 나타나는 것을 확인할 수 있다.
kubectl exec -it netpod -- ping -c 1 $WEBPOD1IP && kubectl exec -it netpod -- ping -c 1 $WEBPOD2IP
kubectl exec -it netpod -- curl -s $WEBPOD1IP && kubectl exec -it netpod -- curl -s $WEBPOD2IP
kubectl exec -it netpod -- curl -s $WEBPOD1IP:8080 ; kubectl exec -it netpod -- curl -s $WEBPOD2IP:8080
Hubble CLI에서도 이와 관련된 내용을 그대로 조회할 수 있다.
이번에는 외부로 트래픽을 보내보도록 하겠다.
kubectl exec -it netpod -- ping -c 1 8.8.8.8 && kubectl exec -it netpod -- curl -s wttr.in/seoul
Hubble CLI에서도 잘 확인할 수 있다.
이렇게 트래픽이 손쉽게 흘러갈 수 있는 이유는 BPF Map이 이미 규정되어 있어 목적지 파드와 통신시 어느곳으로 보내야할지 바로 알수 있다. 이는 cilium의 캐시에 저장되는데 해당 정보는 다음과 같이 확인할 수 있다.
kubectl exec -it $CILIUMPOD0 -n kube-system -c cilium-agent -- cilium map get cilium_ipcache | grep $WEBPOD1IP
각 pod, node 등이 사용하는 터널 엔드포인트와 identity 등이 기록되어 있다.
예를 들어 webpod1은 엔드포인트로 worker-node1의 IP를 가지고 있다.
172.16.2.234/32 identity=3608 encryptkey=0 tunnelendpoint=192.168.10.101, flags=<none> sync
서비스 통신
기존의 Network기반의 로드밸런싱을 사용하게 되면 DNAT가 필요했다. 그러나 Socket 기반으로 로드밸런싱 할 경우 Socket 레벨에서 목적지 IP로 변경해버린다. NAT와 Conntrack Table까지 필요 없기 때문에 파드 자체에서 system call 기반으로 아이피를 바로 변경해버린다. 즉 네트워크 홉을 줄여주고 정말 최적화되어 통신하게 된다.
위 그림을 보면 불필요하게 DNAT를 다녀올 필요없이(왼쪽) pod 자체에서 아이피를 변경해서 바로 목적지로 향한다.(오른쪽)
통신 확인
strace은 시스템 콜 트레이싱 도구로 디버깅을 할 때 사용한다. 시스템 콜의 상태를 분석하는데 사용할 수 있다.
확인을 하기 위해서 기존의 webpod 1과 2를 묶어줄 서비스를 만들고 포트는 80으로 생성하였다.
그리고 서비스의 IP를 가지고 netpod에서 호출을 진행해 보았다.
kubectl exec netpod -- curl -s $SVCIP
그리고 netpod에 가서 tcpdump를 실행해보자. 지금 나의 서비스 IP는 10.10.60.189인데, 해당 IP는 아무리 봐도 tcpdump에 기록되지 않는다. 바로 172.16.0.57(netpod)에서 172.16.1.146(webpod2), 172.16.2.234(webpod1)으로 바로 tcp가 향하는 것을 볼 수 있다.
kubectl exec netpod -- tcpdump -enni any -q
cilium-agent에서도 service list를 확인해보면 서비스에서 연결되어 있는 pod의 목록을 손쉽게 확인할 수 있다.
kubectl exec -it $CILIUMPOD0 -n kube-system -c cilium-agent -- cilium service list
'프로젝트&&스터디 > KANS2기' 카테고리의 다른 글
[KANS-9주차] VPC CNI와 EKS (0) | 2024.10.28 |
---|---|
[KANS-3기] 여러기능 (Network Policy/Bandwidth Manager/L2 Announcements) (3) | 2024.10.27 |
[KANS-7주차] Istio의 Egress Gateway (0) | 2024.10.20 |
[KANS-7주차] Istio에서 Kubernetes Ingress Gateway 활용하기 (5) | 2024.10.19 |
[KANS-7주차] Envoy QuickStart 톺아보기 (0) | 2024.10.18 |