Cilium 이란?
cilium의 기반에는 ebpf라는 리눅스 커널 기술이 사용된다. ebpf는 보안/가시성/네트워킹 제어 로직을 커널에 동적으로 삽입할 수 있는 Linux 커널 기술이다.
또한 cilium은 kube-proxy를 완전히 대체할 수 있다. cilium은 iptables을 이용한 쿠버네티스 트래픽 라우팅의 단점을 보완하여 네트워크 성능을 높히고자 하는 목적을 갖고있다.
iptables를 기반으로 IP/PORT 기반의 전통적인 포워딩 기술은 오랫동안 널리 사용되었고 퍼블릿/프라이빗 클라우드 제품군들 모두 iptables 기반의 Security Group등을 기본으로 제공하고 있고 쿠버네티스마저도 CNI 핵심으로 iptables를 활용하고 있다.
하지만 동적으로 변화하고 복잡한 마이크로서비스를 사용하는 시대에 전통적인 방식의 IP/PORT 관리는 비효율적인 측면이 많다.
위 그림은 cilium이 네트워킹 스택에서 iptables를 우회할 수 있음을 보여준다.
일반적으로 쿠버네티스의 동적 특정으로 인해 iptables의 성능은 규모에 따라 달라진다. 많은 노드/파드/서비스가 있는 대규모 클러스터에서는 일반적으로 파드가 들어오고 나갈 때 업데이트해야 하는 많은 수의 iptables 필터 및 전달 규칙이 있다.
더 나쁜 점은 iptables를 사용하면 하나의 규칙을 변경하면 전체 테이블이 다시 작성된다는 것이다.
배포 규모가 커짐에 따라 파드가 생성되거나 삭제될 때마다 규칙이 수렴되는데 시간이 점점 더 오래 걸리므로 규모에 맞는 올바른 작업이 크게 지연된다.
cilium은 iptables 대신 ebpf 맵에서 파드 엔드포인트를 추적한다.
cilium은 네트워크 뿐만 아니라 모니터링/보안 기능도 제공함으로써 쿠버네티스로 서비스를 운영할 도구의 수를 줄여 운영을 단순화하는 것을 목표로 한다.
Cilium 구성요소
- Agent
- 각 노드에 실행
- 네트워킹, 서비스 로드밸런싱, 네트워크 정책, 모니터링을 수행
- ebpf 가 네트워크를 제어하는 것을 관리
- Client (CLI)
- REST API 이용
- agent 상태 확인
- ebpf 맵에 직접 접근하여 상태를 검증할 수 있는 도구도 제공한다.
- Operator
- 클러스터 전체에서 한번만 처리되어야 하는 작업을 담당한다
- CNI plugin
- 파드 생성/삭제 시 쿠버네티스에 의해 호출
- cilium api와 상호작용하여 파드에 대한 네트워킹/로드밸런싱/네트워크정책을 제공하는 데 필요한 데이터 경로 구성을 트리거
Cilium 라우팅
https://docs.cilium.io/en/stable/network/concepts/routing/
cilium에서 사용하는 ebpf maps의 종류는 다음과 같다. ebpf maps에 라우팅을 위해 필요한 정보들도 저장한다.
TBD...
Hubble 이란?
cilium에서 제공하는 모니터링 도구이다.
ebpf를 활용하면 가시성을 프로그래밍할 수 있으며 Hubble은 ebpf 성능을 최대한 활용하도록 설계되었다.
Hubble을 사용하면 L3/L4 및 심지어 L7에서도 쿠버네티스 클러스터에 대한 서비스 종속성 그래프를 손쉽게 볼 수 있다.
cilium 및 ebpf를 기반으로 구축되어 완전히 투명한 방식으로 네트워킹 인프라는 물론 서비스의 통신 및 동작에 대한 깊은 가시성을 제공한다.
Hubble은 다음과 같은 질문에 답을 줄 수 있다.
service dependencies & communication map
- 어떤 서비스가 서로 통신하고 있나요? 얼마나 자주 통신하고 있나요? 서비스 종속성 그래프는 어떤 모양인가요?
- 어떤 HTTP 호출이 이루어지나요? 서비스는 어떤 kafka 토픽을 consume 하거나 produce 하나요?
network monitoring & alerting
- 네트워크 통신이 실패하나요? 왜 실패하나요? DNS 때문인가요? 애플리케이션 문제인가요 네트워크 문제인가요? 통신이 레이어4(TCP)에서 끊어지나요 7(HTTP)에서 끊어지나요?
- 지난 5분 동안 어떤 서비스에서 DNS 확인 문제가 발생했나요? 최근에 TCP 연결이 중단되었거나 연결 시간이 초과된 서비스는 무엇인가요? 응답되지 않는 TCP SYN 요청의 비율은 얼마인가요?
application monitoring
- 특정 서비스 또는 모든 클러스터에 대한 5xx 또는 4xx HTTP 응답 코드 비율은 얼마나 되나요?
- 어떤 서비스의 성능이 가장 낮나요? 두 서비스 간의 대기 시간은 얼마나 되나요?
security observability
- 네트워크 정책으로 인해 연결이 차단된 서비스는 무엇인가요? 클러스터 외부에서 어떤 서비스에 접근했나요? 어떤 서비스가 특정 DNS 이름을 확인했나요?
Hubble 구성요소
- Server
- 각노드에서 실행되며 cilium에서 ebpf 기반 가시성을 검색한다.
- 고성능과 낮은 오버헤드를 달성하기 위해 cilium 에이전트에 내장돼있다.
- prometheus metrics을 검색하는 grpc 서비스를 제공한다.
- Relay
- 실행 중인 모든 허블 서버를 인식하고 해당 grpc api에 연결하고 클러스터의 모든 서버를 나타내는 api를 제공하여 클러스터 전체에 대한 가시성을 제공하는 독립 실행형 구성요소이다.
- Client (CLI)
- relay의 grpc api 또는 로컬 서버에 연결하여 흐름 이벤트를 검색할 수 있는 명령줄 도구이다.
- Graphical UI (GUI)
- relay 기반 가시성을 활용하여 그래픽 서비스 종속성과 연결 맵을 제공한다.
Install with Kind Cluster
https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/
# kind를 이용한 클러스터 세팅
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
networking:
disableDefaultCNI: true
$ kind create cluster --config=kind-config.yaml
$ kubectl cluster-info --context kind-kind
# cilium 배포를 위한 레파지토리 추가
$ helm repo add cilium https://helm.cilium.io/
# kind 클러스터에서 cilium 이미지를 가져오기 위해 cilium 이미지 로드
$ docker pull quay.io/cilium/cilium:v1.16.1
$ kind load docker-image quay.io/cilium/cilium:v1.16.1
# cilium 배포
$ helm install cilium cilium/cilium --version 1.16.1 \
--namespace kube-system \
--set image.pullPolicy=IfNotPresent \
--set ipam.mode=kubernetes
# 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}
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 45.3M 100 45.3M 0 0 19.8M 0 0:00:02 0:00:02 --:--:-- 32.9M
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 92 100 92 0 0 75 0 0:00:01 0:00:01 --:--:-- 0
cilium-linux-amd64.tar.gz: OK
cilium
# 배포된 cilium 상태 확인
$ cilium status --wait
/¯¯\
/¯¯\__/¯¯\ Cilium: OK
\__/¯¯\__/ Operator: OK
/¯¯\__/¯¯\ Envoy DaemonSet: OK
\__/¯¯\__/ Hubble Relay: disabled
\__/ ClusterMesh: disabled
Deployment cilium-operator Desired: 2, Ready: 2/2, Available: 2/2
DaemonSet cilium-envoy Desired: 2, Ready: 2/2, Available: 2/2
DaemonSet cilium Desired: 2, Ready: 2/2, Available: 2/2
Containers: cilium Running: 2
cilium-operator Running: 2
cilium-envoy Running: 2
Cluster Pods: 3/3 managed by Cilium
Helm chart version:
Image versions cilium quay.io/cilium/cilium:v1.16.1@sha256:0b4a3ab41a4760d86b7fc945b8783747ba27f29dac30dd434d94f2c9e3679f39: 2
cilium-operator quay.io/cilium/operator-generic:v1.16.1@sha256:3bc7e7a43bc4a4d8989cb7936c5d96675dd2d02c306adf925ce0a7c35aa27dc4: 2
cilium-envoy quay.io/cilium/cilium-envoy:v1.29.7-39a2a56bbd5b3a591f69dbca51d3e30ef97e0e51@sha256:bd5ff8c66716080028f414ec1cb4f7dc66f40d2fb5a009fff187f4a9b90b566b: 2
# cilium hubble 활성화
$ cilium hubble enable
# hubble 활성화 확인
$ cilium status
/¯¯\
/¯¯\__/¯¯\ Cilium: OK
\__/¯¯\__/ Operator: OK
/¯¯\__/¯¯\ Envoy DaemonSet: OK
\__/¯¯\__/ Hubble Relay: OK
\__/ ClusterMesh: disabled
DaemonSet cilium-envoy Desired: 2, Ready: 2/2, Available: 2/2
Deployment hubble-relay Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet cilium Desired: 2, Ready: 2/2, Available: 2/2
Deployment cilium-operator Desired: 2, Ready: 2/2, Available: 2/2
Containers: cilium Running: 2
cilium-envoy Running: 2
hubble-relay Running: 1
cilium-operator Running: 2
Cluster Pods: 4/4 managed by Cilium
Helm chart version:
Image versions cilium-envoy quay.io/cilium/cilium-envoy:v1.29.7-39a2a56bbd5b3a591f69dbca51d3e30ef97e0e51@sha256:bd5ff8c66716080028f414ec1cb4f7dc66f40d2fb5a009fff187f4a9b90b566b: 2
hubble-relay quay.io/cilium/hubble-relay:v1.16.1@sha256:2e1b4c739a676ae187d4c2bfc45c3e865bda2567cc0320a90cb666657fcfcc35: 1
cilium-operator quay.io/cilium/operator-generic:v1.16.1@sha256:3bc7e7a43bc4a4d8989cb7936c5d96675dd2d02c306adf925ce0a7c35aa27dc4: 2
cilium quay.io/cilium/cilium:v1.16.1@sha256:0b4a3ab41a4760d86b7fc945b8783747ba27f29dac30dd434d94f2c9e3679f39: 2
# hubble cli 설치
$ 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}
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 7015k 100 7015k 0 0 4430k 0 0:00:01 0:00:01 --:--:-- 31.5M
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 92 100 92 0 0 73 0 0:00:01 0:00:01 --:--:-- 0
hubble-linux-amd64.tar.gz: OK
hubble
# hubble 상태 확인
$ hubble status
Healthcheck (via localhost:4245): Ok
Current/Max Flows: 1,942/8,190 (23.71%)
Flows/s: 6.22
Connected Nodes: 2/2
$ hubble observe
Sep 21 08:24:26.505: 10.244.1.137:48534 (host) -> kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Sep 21 08:24:26.505: 10.244.1.137:48534 (host) -> kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-endpoint FORWARDED (TCP Flags: SYN)
Sep 21 08:24:26.505: 10.244.1.137:48534 (host) <- kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-stack FORWARDED (TCP Flags: SYN, ACK)
Sep 21 08:24:26.505: 10.244.1.137:48534 (host) -> kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-endpoint FORWARDED (TCP Flags: ACK)
Sep 21 08:24:26.505: 10.244.1.137:48532 (host) -> kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Sep 21 08:24:26.505: 10.244.1.137:48534 (host) <- kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-stack FORWARDED (TCP Flags: ACK, PSH)
Sep 21 08:24:26.505: 10.244.1.137:48532 (host) <- kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-stack FORWARDED (TCP Flags: ACK, PSH)
Sep 21 08:24:26.505: 10.244.1.137:48534 (host) -> kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-endpoint FORWARDED (TCP Flags: ACK, FIN)
Sep 21 08:24:26.505: 10.244.1.137:48532 (host) -> kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-endpoint FORWARDED (TCP Flags: ACK, FIN)
Sep 21 08:24:26.505: 10.244.1.137:48532 (host) <- kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-stack FORWARDED (TCP Flags: ACK, FIN)
Sep 21 08:24:26.505: 10.244.1.137:48532 (host) -> kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-endpoint FORWARDED (TCP Flags: ACK)
Sep 21 08:24:26.505: 10.244.1.137:48534 (host) <- kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-stack FORWARDED (TCP Flags: ACK, FIN)
Sep 21 08:24:26.505: 10.244.1.137:48534 (host) -> kube-system/hubble-relay-7749c4fc9-vgdb2:4222 (ID:6243) to-endpoint FORWARDED (TCP Flags: ACK)
Sep 21 08:24:26.984: kube-system/hubble-relay-7749c4fc9-vgdb2:37850 (ID:6243) <- 172.18.0.2:4244 (host) to-endpoint FORWARDED (TCP Flags: ACK)
Sep 21 08:24:26.984: kube-system/hubble-relay-7749c4fc9-vgdb2:37850 (ID:6243) -> 172.18.0.2:4244 (host) to-stack FORWARDED (TCP Flags: ACK)
Sep 21 08:24:26.984: kube-system/hubble-relay-7749c4fc9-vgdb2:41234 (ID:6243) <- 172.18.0.3:4244 (kube-apiserver) to-endpoint FORWARDED (TCP Flags: ACK)
Sep 21 08:24:26.984: kube-system/hubble-relay-7749c4fc9-vgdb2:41234 (ID:6243) -> 172.18.0.3:4244 (kube-apiserver) to-stack FORWARDED (TCP Flags: ACK)
Sep 21 08:24:29.288: kube-system/hubble-relay-7749c4fc9-vgdb2:44888 (ID:6243) <- 172.18.0.2:443 (host) to-endpoint FORWARDED (TCP Flags: ACK)
Sep 21 08:24:29.288: kube-system/hubble-relay-7749c4fc9-vgdb2:44888 (ID:6243) -> 172.18.0.2:4244 (host) to-stack FORWARDED (TCP Flags: ACK)
Sep 21 08:24:30.788: 10.244.0.254:56542 (host) -> kube-system/coredns-6f6b679f8f-c6wjs:8181 (ID:18604) to-endpoint FORWARDED (TCP Flags: ACK, FIN)
Sep 21 08:24:30.788: 10.244.0.254:56542 (host) <- kube-system/coredns-6f6b679f8f-c6wjs:8181 (ID:18604) to-stack FORWARDED (TCP Flags: ACK, FIN)
Sep 21 08:24:30.788: 10.244.0.254:56542 (host) -> kube-system/coredns-6f6b679f8f-c6wjs:8181 (ID:18604) to-endpoint FORWARDED (TCP Flags: ACK)
Sep 21 08:24:30.809: 10.244.0.254:56130 (host) -> kube-system/coredns-6f6b679f8f-4psmq:8181 (ID:18604) to-endpoint FORWARDED (TCP Flags: SYN)
Sep 21 08:24:30.809: 10.244.0.254:56130 (host) <- kube-system/coredns-6f6b679f8f-4psmq:8181 (ID:18604) to-stack FORWARDED (TCP Flags: SYN, ACK)
Sep 21 08:24:30.809: 10.244.0.254:56130 (host) -> kube-system/coredns-6f6b679f8f-4psmq:8181 (ID:18604) to-endpoint FORWARDED (TCP Flags: ACK)
Sep 21 08:24:30.809: 10.244.0.254:56130 (host) -> kube-system/coredns-6f6b679f8f-4psmq:8181 (ID:18604) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Sep 21 08:24:30.809: 10.244.0.254:40442 (host) -> kube-system/coredns-6f6b679f8f-4psmq:8080 (ID:18604) to-endpoint FORWARDED (TCP Flags: SYN)
Sep 21 08:24:30.809: 10.244.0.254:40442 (host) <- kube-system/coredns-6f6b679f8f-4psmq:8080 (ID:18604) to-stack FORWARDED (TCP Flags: SYN, ACK)
Sep 21 08:24:30.809: 10.244.0.254:40442 (host) -> kube-system/coredns-6f6b679f8f-4psmq:8080 (ID:18604) to-endpoint FORWARDED (TCP Flags: ACK)
Sep 21 08:24:30.809: 10.244.0.254:40442 (host) -> kube-system/coredns-6f6b679f8f-4psmq:8080 (ID:18604) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Sep 21 08:24:30.809: 10.244.0.254:40442 (host) <- kube-system/coredns-6f6b679f8f-4psmq:8080 (ID:18604) to-stack FORWARDED (TCP Flags: ACK, PSH)
Sep 21 08:24:30.809: 10.244.0.254:40442 (host) <- kube-system/coredns-6f6b679f8f-4psmq:8080 (ID:18604) to-stack FORWARDED (TCP Flags: ACK, FIN)
Sep 21 08:24:30.809: 10.244.0.254:56130 (host) <- kube-system/coredns-6f6b679f8f-4psmq:8181 (ID:18604) to-stack FORWARDED (TCP Flags: ACK, PSH)
Sep 21 08:24:30.809: 10.244.0.254:56130 (host) <- kube-system/coredns-6f6b679f8f-4psmq:8181 (ID:18604) to-stack FORWARDED (TCP Flags: ACK, FIN)
Sep 21 08:24:30.810: 10.244.0.254:40442 (host) -> kube-system/coredns-6f6b679f8f-4psmq:8080 (ID:18604) to-endpoint FORWARDED (TCP Flags: ACK, FIN)
Sep 21 08:24:30.810: 10.244.0.254:56130 (host) -> kube-system/coredns-6f6b679f8f-4psmq:8181 (ID:18604) to-endpoint FORWARDED (TCP Flags: ACK, FIN)
Sep 21 08:24:31.588: 10.244.0.254:33368 (remote-node) <- 10.244.1.174:4240 (health) to-overlay FORWARDED (TCP Flags: ACK)
Sep 21 08:24:31.589: 10.244.0.254:43562 (host) <- 10.244.0.115:4240 (health) to-stack FORWARDED (TCP Flags: ACK)
Sep 21 08:24:31.589: 10.244.0.254:43562 (host) -> 10.244.0.115:4240 (health) to-endpoint FORWARDED (TCP Flags: ACK)
Sep 21 08:24:31.589: 10.244.0.254:33368 (remote-node) <> 10.244.1.174:4240 (health) to-overlay FORWARDED (TCP Flags: ACK)
$ cilium hubble enable --ui
$ kubectl port-forward -n kube-system svc/hubble-ui 12000:80 --address='0.0.0.0.0'
# 데모 앱 배포
스타워즈에서 영감을 받은 deathstar, Tiefighter, xwing 세 가지 마이크로서비스 애플리케이션이 있다.
$ kubectl create -f https://raw.githubusercontent.com/cilium/cilium/1.16.2/examples/minikube/http-sw-app.yaml
service/deathstar created
deployment.apps/deathstar created
pod/tiefighter created
pod/xwing created
$ kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/deathstar-bf77cddc9-6r8mb 1/1 Running 0 30s
pod/deathstar-bf77cddc9-k9npz 1/1 Running 0 30s
pod/tiefighter 1/1 Running 0 30s
pod/xwing 1/1 Running 0 30s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/deathstar ClusterIP 10.96.15.38 <none> 80/TCP 31s
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d1h
# Hubble UI 확인
마이크로서비스 앱이 배포된 default 네임스페이스를 확인한다.
cilium은 각 노드에 에이전트를 설치하는데 cilium 파드에서 endpoint list 명령을 통해 해당 에이전트가 관리하는 파드들을 확인할 수 있다.
$ kubectl -n kube-system get pods -l k8s-app=cilium
NAME READY STATUS RESTARTS AGE
cilium-fmhhf 1/1 Running 1 (35m ago) 5d2h
cilium-sb5cc 1/1 Running 1 (35m ago) 5d2h
아직 파드들에 어떤 네트워크 정책도 적용되지 않았기 때문에 POLICY가 전부 Disabled 상태인 것을 확인할 수 있다.
(모든 포드에 대한 ingress(들어오는 트래픽)와 egress(나가는 트래픽) 정책이 비활성화된 상태 → 트래픽 제어가 이루어지지 않고 있다는 의미)
$ kubectl -n kube-system exec cilium-fmhhf -- cilium-dbg endpoint list
Defaulted container "cilium-agent" out of: cilium-agent, config (init), mount-cgroup (init), apply-sysctl-overwrites (init), mount-bpf-fs (init), clean-cilium-state (init), install-cni-binaries (init)
ENDPOINT POLICY (ingress) POLICY (egress) IDENTITY LABELS (source:key[=value]) IPv6 IPv4 STATUS
ENFORCEMENT ENFORCEMENT
570 Disabled Disabled 56702 k8s:app.kubernetes.io/name=deathstar 10.244.1.92 ready
k8s:class=deathstar
k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default
k8s:io.cilium.k8s.policy.cluster=default
k8s:io.cilium.k8s.policy.serviceaccount=default
k8s:io.kubernetes.pod.namespace=default
k8s:org=empire
1864 Disabled Disabled 25873 k8s:app.kubernetes.io/name=xwing 10.244.1.37 ready
k8s:class=xwing
k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default
k8s:io.cilium.k8s.policy.cluster=default
k8s:io.cilium.k8s.policy.serviceaccount=default
k8s:io.kubernetes.pod.namespace=default
k8s:org=alliance
2437 Disabled Disabled 56702 k8s:app.kubernetes.io/name=deathstar 10.244.1.78 ready
k8s:class=deathstar
k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default
k8s:io.cilium.k8s.policy.cluster=default
k8s:io.cilium.k8s.policy.serviceaccount=default
k8s:io.kubernetes.pod.namespace=default
k8s:org=empire
3896 Disabled Disabled 4673 k8s:app.kubernetes.io/name=tiefighter 10.244.1.159 ready
k8s:class=tiefighter
k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default
k8s:io.cilium.k8s.policy.cluster=default
k8s:io.cilium.k8s.policy.serviceaccount=default
k8s:io.kubernetes.pod.namespace=default
k8s:org=empire
deathstar 서비스의 관점에서 볼 때 org=empire 레이블이 있는 선박만 연결 및 착륙 요청이 허용돼야한다. 그러나 현재 시행되는 규칙이 없으므로 xwing과 Tiefighter 모두 착륙을 요청할 수 있다.
$ kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed
$ kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed
Cilium을 사용하는 경우 보안 정책을 정의할 때 엔드포인트 IP 주소는 관련이 없다. 대신 파드에 할당된 레이블을 사용하여 보안 정책을 정의할 수 있다. 정책은 클러스터 내에서 언제 어디서 실행되는지에 관계 없이 레이블을 기반으로 올바른 파드에 적용된다.
deathstar 착륙 요청을 라벨(org=empire)이 있는 선박만으로 제한하는 정책부터 시작하겠다. 이는 org=empire 라벨이 없는 선박이 deathstar 서비스에 연결하는 것을 허용하지 않는다. 이는 IP 프로토콜(L3)과 TCP 프로토콜(L4)만 필터링하는 간단한 정책이므로 L3/L4 네트워크 보안 정책이라고 한다.
우리는 다음 CiliumNetworkPolicy를 사용하여 위 그림의 목표를 달성할 수 있다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "rule1"
spec:
description: "L3-L4 policy to restrict deathstar access to empire ships only"
endpointSelector:
matchLabels:
org: empire
class: deathstar
ingress:
- fromEndpoints:
- matchLabels:
org: empire
toPorts:
- ports:
- port: "80"
protocol: TCP
$ kubectl create -f https://raw.githubusercontent.com/cilium/cilium/1.16.2/examples/minikube/sw_l3_l4_policy.yaml
ciliumnetworkpolicy.cilium.io/rule1 created
이제 다시 착륙 요청을 해보면 org=empire 라벨이 있는 tiefighter 파드만 성공한다. xwing 파드가 차단된다.
$ kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed
$ kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
timeout error
cilium 엔드포인트 목록을 다시 확인하면 org=empire 및 class=deathstar 레이블이 있는 파드에 수신 정책이 확성화된 것을 볼 수 있다.
$ kubectl -n kube-system exec cilium-fmhhf -- cilium-dbg endpoint list
Defaulted container "cilium-agent" out of: cilium-agent, config (init), mount-cgroup (init), apply-sysctl-overwrites (init), mount-bpf-fs (init), clean-cilium-state (init), install-cni-binaries (init)
ENDPOINT POLICY (ingress) POLICY (egress) IDENTITY LABELS (source:key[=value]) IPv6 IPv4 STATUS
ENFORCEMENT ENFORCEMENT
570 Enabled Disabled 56702 k8s:app.kubernetes.io/name=deathstar 10.244.1.92 ready
k8s:class=deathstar
k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default
k8s:io.cilium.k8s.policy.cluster=default
k8s:io.cilium.k8s.policy.serviceaccount=default
k8s:io.kubernetes.pod.namespace=default
k8s:org=empire
1864 Disabled Disabled 25873 k8s:app.kubernetes.io/name=xwing 10.244.1.37 ready
k8s:class=xwing
k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default
k8s:io.cilium.k8s.policy.cluster=default
k8s:io.cilium.k8s.policy.serviceaccount=default
k8s:io.kubernetes.pod.namespace=default
k8s:org=alliance
2437 Enabled Disabled 56702 k8s:app.kubernetes.io/name=deathstar 10.244.1.78 ready
k8s:class=deathstar
k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default
k8s:io.cilium.k8s.policy.cluster=default
k8s:io.cilium.k8s.policy.serviceaccount=default
k8s:io.kubernetes.pod.namespace=default
k8s:org=empire
3896 Disabled Disabled 4673 k8s:app.kubernetes.io/name=tiefighter 10.244.1.159 ready
k8s:class=tiefighter
k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name=default
k8s:io.cilium.k8s.policy.cluster=default
k8s:io.cilium.k8s.policy.serviceaccount=default
k8s:io.kubernetes.pod.namespace=default
k8s:org=empire
kubectl을 통해 정책 세부정보를 검사할 수도 있다.
$ kubectl get cnp
NAME AGE
rule1 6m40s
$ kubectl describe cnp rule1
Name: rule1
Namespace: default
Labels: <none>
Annotations: <none>
API Version: cilium.io/v2
Kind: CiliumNetworkPolicy
Metadata:
Creation Timestamp: 2024-09-26T10:36:37Z
Generation: 1
Resource Version: 11062
UID: 7ad3e283-b175-4e28-a671-ce139326b00c
Spec:
Description: L3-L4 policy to restrict deathstar access to empire ships only
Endpoint Selector:
Match Labels:
Class: deathstar
Org: empire
Ingress:
From Endpoints:
Match Labels:
Org: empire
To Ports:
Ports:
Port: 80
Protocol: TCP
Status:
Conditions:
Last Transition Time: 2024-09-26T10:36:37Z
Message: Policy validation succeeded
Status: True
Type: Valid
Events: <none>
지금까지와 같은 간단한 시나리오에서는 tiefighter/xwing에 deathstar에 대한 권한을 부여하거나 부여하지 않는 것으로 충분했다.
그러나 마이크로서비스 간에 가장 강력한 보안(최소 권한 격리)을 제공하려면 deathstar의 API를 호출하는 각 서비스가 합법적인 작업에 필요한 일련의 HTTP 요청만 생성하도록 제한해야한다.
예를 들어, deathstar 서비스가 호출해서는 안되는 일부 유지 관리 API를 노출하여 누군가 해당 API를 호출할 경우 보안에 부정적인 영향을 미칠 수 있다.
$ kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port
Panic: deathstar exploded
goroutine 1 [running]:
main.HandleGarbage(0x2080c3f50, 0x2, 0x4, 0x425c0, 0x5, 0xa)
/code/src/github.com/empire/deathstar/
temp/main.go:9 +0x64
main.main()
/code/src/github.com/empire/deathstar/
temp/main.go:5 +0x85
Cilium은 HTTP게층(L7)정책을 시행하여 tiefighter가 도달할 수 있는 URL을 제한할 수 있다.
다음은 tiefighter를 POST /v1/request-landing API 호출만 수행하도록 제한하고 다른 모든 호출(PUT /v1/exhaust-port 등)을 허용하지 않도록 하여 정책을 확장하는 예제 yaml이다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "rule1"
spec:
description: "L7 policy to restrict access to specific HTTP call"
endpointSelector:
matchLabels:
org: empire
class: deathstar
ingress:
- fromEndpoints:
- matchLabels:
org: empire
toPorts:
- ports:
- port: "80"
protocol: TCP
rules:
http:
- method: "POST"
path: "/v1/request-landing"
$ kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/1.16.2/examples/minikube/sw_l3_l4_l7_policy.yaml
ciliumnetworkpolicy.cilium.io/rule1 configured
$ kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed
$ kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port
Access denied
UseCases
cilium은 쿠버네티스 CNI 종류 중 하나로 알려져 있지만 단순히 네트워크의 역할만 하지 않는다.
크게 네트워크/모니터링/보안 3가지 영역을 위한 기능들을 제공하고 있으며 각 분야에서 어떤 기능들을 주로 제공하는지 확인해보자.
Network
High Performance Networking (CNI)
쿠버네티스에서 사용할 수 있는 CNI는 수십개가 있지만 기능, 규모, 성능은 크게 다르다.
이들 중 다수는 쿠버네티스 환경의 규모와 변동을 처리할 수 없는 레거시기술(iptables)에 의존하여 대기 시간이 늘어나고 처리량이 감소한다.
또한 대부분의 CNI는 L3/L4 네트워크 정책만 지원하고 그 이상은 거의 제공하지 않는다.
cilium은 수백, 수천 개의 컨테이너가 몇 초 내에 생성되고 파괴되는 대규모의 매우 동적인 클라우드 네이티브 환경을 위해 만들어졌다.
cilium은 ebpf를 사용하여 대규모 iptables 규칙의 함정을 피한다. ebpf 기반 네트워킹은 대규모 작업에 최적화되어있으며 네트워크 병목 현상에 대해 걱정하지 않고 운영을 확장할 수 있다.
Layer4 Load Balancing
cilium은 BGP로 트래픽을 유치하고 XDP 및 ebpf를 활용하여 트래픽을 가속화할 수 있다. 이러한 기술을 함께 사용하면 매우 강력하고 안전한 로드밸런싱 구현이 가능해진다.
Badwidth and Latency Optimization
cilium의 Badwidth Manager를 사용하면 단 한 줄의 YAML로 파드당 속도를 제한할 수 있다.
Kube-proxy Replacement
iptables와 netfilter는 서비스 추상화를 구현하기 위한 kube-proxy의 두 가지 기본 기술이다. 클라우드 네이티브 시대에는 특히 성능, 안정성, 확장성이 중요한 만큼 해당 도구들은 더 이상 가장 적합한 도구가 아니다.
kube-proxy를 cilium으로 전환하는 것은 매우 쉽다. cilium은 Kubernetes API와 완벽하게 호환되는 쿠버네티스 네이티브 구현을 제공하기 때문에 kube-proxy를 cilium으로 교체하는 것은 간단한 프로세스이다.
Cluster Mesh
Cilium Cluster Mesh를 사용하면 모든 클러스터가 Cilium을 CNI로 실행할 경우, 파드가 다른 클러스터에 있는 서비스를 검색하고 접근할 수 있도록 네트워크를 연결할 수 있다.
Cluster Mesh는 여러 쿠버네티스 클러스터에 걸쳐 파드 ip 라우팅을 처리할 수 있다.
이를 통해 파드는 클러스터 간에 원활하게 통신할 수 있어 마이크로서비스 아키텍처의 전반적인 효율성이 향상된다.
Cluster Mesh를 사용하면 모든 클러스터 간에 시크릿 관리, 로깅, 모니터링, DNS와 같은 서비스를 공유할 수 있다.
이는 운영 오버헤드를 줄이고 관리를 단순화하며 테넌트 클러스터 간의 격리를 유지한다.
BGP
cilium은 BGP 성능을 증폭시켜 클라우드 환경에서 확장 가능하고 안전한 고속 라우팅을 제공한다.
cilium의 BGP 지원은 기존 네트워킹 인프라와 간단하고 쉽게 통합되도록 설계되었다.
cilium은 BGP 없이도 ebpf와 리눅스 라우팅 테이블을 통해 클러스터 내에서 효율적인 네트워크 트래픽 라우팅을 수행할 수 있다.
BGP는 대규모 또는 멀티클러스터 환경에서 경로 관리를 더 잘하기 위해 사용되며, cilium은 기본적으로 클러스터 내부의 라우팅을 처리하는 데 있어서 BGP 없이도 충분히 성능을 발휘할 수 있다.
Service Mesh
기존 서비스메시는 장점에도 불구하고 심각한 문제를 야기할 수 있다.
IP 및 포트 기반 네트워크 정책의 복잡성과 오류 발생 가능성, 프록시 기반 아키텍처로 인한 성능 오버헤드, 서비스 간 통신의 제한된 가시성, 기존 인프라와의 상호 운영성 문제, 서비스 수 및 트래픽 볼륨 증가에 따른 확장성 문제, 운영 및 리소스 오버헤드 등.
Cilium Service Mesh는 eBPF를 사용하여 메시 계층을 커널에서 직접 통신함으로써 사이드카 프록시가 필요하지 않도록 하여 기존 서비스메시 프레임워크를 재정의한다.
또한 네트워킹 및 애플리케이션 프로토콜 계층 모두에서 연결을 관리하고 IP, TCP, UDP, HTTP, Kafka, gRPC 및 DNS와 같은 프로토콜을 보다 효율적으로 처리한다.
ebpf를 사용함으로써 기존 프록시의 성능 단점을 우회하여 서비스 간의 직접적이고 효율적인 통신을 가능하게 한다.
Gateway API
Gateway API는 전통적으로 트래픽을 쿠버네티스 클러스터로 라우팅하는 데 사용됐던 Ingress API의 제한 사항을 해결한다.
Ingress API는 경로 및 호스트 규칙을 기반으로 하는 기본 라우팅을 지원하지만 고급 라우팅 기능에 대한 지원이 부족하고 HTTP, HTTPS 트래픽만 지원하며 사용자/운영자 문제를 분리하지 않았다.
Gateway API는 이러한 제약을 극복하여 트래픽 엔지니어링에 대한 강력하고 확장 가능한 역할 중심 접근 방식을 제공한다.
Gateway API는 인프라 제공자, 클러스터 운영자, 애플리케이션 개발자 등 다양한 운영 역할을 염두에 두고 설계되었다.
예를 들어 애플리케이션 개발자는 지정된 네임스페이스에서 Route 개체를 생성할 수 있지만 게이트웨이 구성을 수정하거나 다른 네임스페이스의 Route 개체를 편집할 수는 없다.
Observability
Service Map
클라우드 네이티브 환경의 문제를 해결할 때 문제는 네트워크, 환경, 종속성 계층 사이에 숨어 있을 수 있다.
예를 들어, DNS가 제대로 작동하는지, 정책 관련 문제로 애플리케이션이 실패하는지, 트래픽이 어디서 차단되는지 등의 문제를 확인하기 어려울 수 있지만 이런 문제 해결을 위해 로그를 검토하는 것은 어렵고 시간이 많이 걸리는 프로세스일 수 있다.
ebpf를 사용하면 모든 가시성을 프로그래밍할 수 있으며 깊고 상세한 가시성을 제공하는 동시에 오버헤드를 최소화하는 동적 접근 방식이 가능하다.
단순히 kubectl get pods를 보는 것 만으로는 각 서비스나 외부 API 또는 데이터베이스 간의 종속성을 나타내지 않는다.
Hubble은 L3/L4 및 L7 수준에서 쿠버네티스 클러스터 내의 서비스 종속성을 손쉽게 자동으로 제공한다.
이를 통해 사용자 친화적인 시각화 및 데이터 흐름 필터링이 Service Map으로 가능해지며 서비스 종속성을 쉽게 관리할 수 있다.
Metrics & Tracing Export
cilium의 metric/trace export 기능은 사용자가 쿠버네티스 환경을 쉽게 모니터링하고, 분석하고, 최적화할 수 있도록 지원하는 통합된 솔루션을 제공한다.
cilium을 통해 사용자는 애플리케이션과 네트워크에 대한 깊이있는 가시성을 확보할 수 있으며 설정 및 구성 과정도 간소화할 수 있다.
또한 cilium은 Jaeger, Zipkin, OpenTelemetry와 같은 다양한 추적 시스템과 통합되어 분산 추적 기능을 제공한다.
cilium은 성능 저하 없이 대용량 데이터를 처리하도록 최적화되어있다.
cilium은 애플리케이션의 대기시간, 요청비율, 오류비율을 포함한 다양한 메트릭을 캡처한다.
이러한 메트릭은 기존 모니터링 및 시각화 도구와 쉽게 통합되어 네트워크 성능을 실시간으로 추적할 수 있다.
Security
Transparent encryption
많은 규정 준수 프레임워크에는 암호화가 필요하지만 쿠버네티스에는 기본 파드간 암호화가 부족하다.
이 문제에 대한 두 가지 일반적인 해결 방법은 애플리케이션 내에 암호화를 내장하거나 서비스메시를 사용하는 것이다.
앱 내에 암호화를 포함시키는 것은 복잡하며 애플리케이션 및 보안 전문 지식이 필요하다. 반면에 대부분의 서비스메시 구현은 매우 복잡하고 관리 및 운영이 어렵다.
cilium은 애플리케이션 변경이나 추가 프록시(서비스메시) 없이 단 하나의 스위치만으로 모든 노드 간 트래픽을 암호화할 수 있는 간단한 솔루션을 제공한다.
cilium은 자동으로 암호화 키를 교체하는 기능을 제공하며 중첩되는 키(키 교체 과정에서 새로운 키와 기존 키가 함께 유효한 기간이 존재)를 사용하여 서비스 중단 없이 안전하게 키를 교체할 수 있다.
또한, 커널 내에서 IPsec 또는 WireGuard를 통해 효율적인 데이터 경로 암호화를 지원하며 UDP와 같은 비표준 트래픽을 포함한 모든 트래픽을 암호화할 수 있다.
모든 클러스터의 모든 노드에 공통 키를 설정하기만 하면 노드 간의 모든 통신이 자동으로 암호화된다.
Network Policy
IP가 빠르게 변경되는 경우 어떻게 세분화된 보안 정책을 구현할 수 있을까? 최신 시스템은 IP를 동적으로 변동시키는 경우가 많아 보안 정책 확장을 위해 TCP/UDP 포트 및 IP 주소에만 전적으로 의존하기 어렵다.
cilium은 L3/L4를 위한 쿠버네티스 Network Policy를 기반으로 구현됐으며 HTTP, Kafka, gRPC 등과 같은 일반적인 프로토콜에 대한 세분화된 API 수준 보안을 위해 L7 정책으로 확장했다.
예를 들어 role=frontend 라벨이 있는 엔드포인트는 REST API 호출 GET /userdata/만 수행할 수 있으며 다른 모든 API 상호 작용은 제한할 수 있다.
cilium은 레이블과 메타데이터에서 파생된 워크로드 아이덴티티를 사용하여 네트워크 주소 지정에서 보안을 분리하므로 지속적인 보안 규칙 업데이트 없이 보다 유연하고 효율적인 확장이 가능하다.
cilium은 간단하고 직관적인 네트워크 정책 편집기 UI를 제공한다.
https://editor.networkpolicy.io/
'클라우드 > Kubernetes(쿠버네티스)' 카테고리의 다른 글
[kubernetes] Service (Headless Service, ExternalName), Endpoint (0) | 2024.08.13 |
---|---|
[Kubernetes] ArgoCD (0) | 2024.07.30 |
kube-proxy, CNI, coreDNS (0) | 2024.07.16 |
[쿠버네티스] 클러스터 구축 (0) | 2024.06.08 |
[kubernetes] kubernetes의 update 종류와 동작 방법 (apply, edit, patch, replace) (0) | 2023.08.18 |