2025.07.26 - [K8S/🔥 network study🔥] - [cilium] 스타워즈 데모로 cilium 테스트 해보기
[cilium] 스타워즈 데모로 cilium 테스트 해보기
스타워즈 데모로 테스트 해보기cilium에서는 샘플 애플리케이션으로 스타워즈 데모를 제공합니다.https://docs.cilium.io/en/stable/gettingstarted/demo/ 데모 환경 소개아래의 파일을 배포하면 데모환경은 구
nuguni.tistory.com
이전에 스타워즈 데모를 통해 http 통신 테스트를 해보았다면 이번엔 다른 등장인물들로 이어서 grpc 통신 테스트를 해보려고 합니다.
(공식 문서: https://docs.cilium.io/en/stable/security/grpc/)
테스트 시나리오는 다음과 같습니다. (사실 중요하지 않음)
레아와 다른 반란군은 스토름트루퍼를 피해 밀레니엄 팔콘이 주기된 우주항 플랫폼으로 가는 도중입니다. 하지만 플랫폼으로 향하는 문이 닫혀 있고 접근 코드가 변경되어 있습니다. 이때 R2-D2가 공용 터미널(클라이언트)을 통해 클라우드 시티 컴퓨터 시스템(서버)에 접속하여 보안을 비활성화하고, 문을 열어 반란군이 간발의 차이로 탈출하게 됩니다.
이번 테스트에서 클라우드 시티 내부 컴퓨터 시스템은 gRPC 기반 서비스로 만들어져있다고 가정합니다.
테스트 환경 구성
cc-door-app.yaml 파일에는 Door Manager 서비스용 Deployment, terminal-87을 나타내는 Pod, Door Manager 서비스용 Service가 포함됩니다.

- cc-door-mgr: gRPC로 만들어진 Door Manager 서비스가 실행되는 단일 파드
- terminal-87: 클라우드 시티 곳곳에 있는 공용 네트워크 액세스 터미널 중 하나. 반란군이 탈출을 시도하는 동안 R2-D2가 terminal-87에 접속합니다. 이 터미널은 Door Manager 서비스와 통신하는 gRPC 클라이언트 입니다.
먼저 cilium을 설치합니다.
helm install cilium cilium/cilium --namespace kube-system \
--set k8sServiceHost=auto --set ipam.mode="cluster-pool" \
--set k8s.requireIPv4PodCIDR=true --set ipv4NativeRoutingCIDR=10.244.0.0/16 \
--set routingMode=native --set autoDirectNodeRoutes=true --set endpointRoutes.enabled=true \
--set kubeProxyReplacement=true --set bpf.masquerade=true --set installNoConntrackIptablesRules=true \
--set endpointHealthChecking.enabled=false --set healthChecking=false \
--set hubble.enabled=true --set hubble.relay.enabled=true --set hubble.ui.enabled=true \
--set hubble.ui.service.type=NodePort --set hubble.ui.service.nodePort=30003 \
--set prometheus.enabled=true --set operator.prometheus.enabled=true --set hubble.metrics.enableOpenMetrics=true \
--set hubble.metrics.enabled="{dns,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 localRedirectPolicy=true --set l2announcements.enabled=true \
--set operator.replicas=1 --set debug.enabled=true
다음 명령어로 예제 앱을 배포합니다.
kubectl create -f https://raw.githubusercontent.com/cilium/cilium/1.18.1/examples/kubernetes-grpc/cc-door-app.yaml
배포된 서비스를 확인해봅시다.
kubectl get pods,svc

그리고 이제 terminal-8(Door 서비스의 클라이언트)이 제대로 동작하는지 확인해보도록 합니다. 컨테이너 안에 있는 Python gRPC 클라이언트(cc_door_client.py)를 실행해보겠습니다.
# 문 이름 확인하기
kubectl exec terminal-87 -- python3 /cloudcity/cc_door_client.py GetName 1
# 문 위치 확인하기
kubectl exec terminal-87 -- python3 /cloudcity/cc_door_client.py GetLocation 1


공용 터미널에서 문 이름과 위치를 확인할 수 있지만 그 외에도 access code를 설정할 수도 있습니다.
# access code 설정하기
kubectl exec terminal-87 -- python3 /cloudcity/cc_door_client.py SetAccessCode 1 999

서비스로의 접근 제어를 전통적인 IP/포트 기반 방화벽만 한다면, GetName과 GetLocation 호출뿐 아니라 SetAccessCode 같은 민감한 호출도 그대로 노출되게 됩니다.
NetworkPolicy로 grpc 접근 막기

Cilium을 사용하여 어떻게 이 보안 허점을 막고 SetAccessCode와 GetStatus 요청은 차단하면서도 GetName, GetLocation, RequestMaintenance는 허용할 수 있을까요?
gRPC는 HTTP 위에서 동작하므로, gRPC 호출이 HTTP URL로 어떻게 매핑되는지를 이해해봐야 합니다.
각 gRPC 메서드는 다음 형태의 HTTP POST 호출로 매핑됩니다
/cloudcity.DoorManager/<method-name>
이 정보를 이용하여 Cilium의 HTTP 인지형 필터를 적용해 공용 터미널이 Door 서비스의 전체 gRPC 메서드 중 일부만 호출할 수 있도록 제한하면 됩니다.
cat << EOF | kubectl apply -f -
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "rule1"
spec:
description: L7 policy to allow public terminals to call GetName, GetLocation, and RequestMaintenance, but not GetState, or SetAccessCode on the Door Manager Service
endpointSelector:
matchLabels:
app: cc-door-mgr
ingress:
- fromEndpoints:
- matchLabels:
app: public-terminal
toPorts:
- ports:
- port: "50051"
protocol: TCP
rules:
http:
# GetName, GetLocation, RequestMaintenance만 허용하기
- method: "POST"
path: "/cloudcity.DoorManager/GetName"
- method: "POST"
path: "/cloudcity.DoorManager/GetLocation"
- method: "POST"
path: "/cloudcity.DoorManager/RequestMaintenance"
EOF

CiliumNetworkPolicy는 정의된 목록만을 허용합니다. 즉, 위에서 정의되어있지 않은 요청(예: SetAccessCode)은 허용되지 않습니다.
위 규칙은 수신(ingress) 방향으로 cc-door-mgr 파드에 대한 연결에 적용됩니다. 또한 “fromEndpoints” 섹션에 지정된 대로 app: public-terminal 라벨을 가진 발신 파드에서 오는 연결에 적용됩니다.
그리고 TCP 50051로 향하는 gRPC 연결을 명시적으로 매칭하고, 허용할 URL만 화이트리스트로 지정합니다.
이제 보안 정책이 적용된 상태에서도 GetLocation 같은 무해한 호출은 정상 호출이 되는지 확인해보겠습니다.
kubectl exec terminal-87 -- python3 /cloudcity/cc_door_client.py GetLocation 1

하지만 다시 SetAccessCode를 호출하면 거부됩니다:
kubectl exec terminal-87 -- python3 /cloudcity/cc_door_client.py SetAccessCode 1 999

이제 Cilium 네트워크 정책 덕분에 호출이 차단됩니다. 또한 전통적 방화벽이 패킷을 드롭해 네트워크 오류와 구분이 되지 않게 만드는 것과 달리, Cilium은 API 레이어에서 동작하므로 커스텀 gRPC 상태 코드 7: PERMISSION_DENIED로 의도적으로 보안상의 이유로 거부되었음을 명확히 응답할 수 있습니다.
'K8S > 🔥 network study🔥' 카테고리의 다른 글
| [cilium] Host 방화벽 설정해보기 (0) | 2025.09.05 |
|---|---|
| 로컬에서 쿠버네티스 api 서버에 List 호출 테스트 (1) | 2025.08.30 |
| perf-tests로 쿠버네티스 성능 테스트해보기 (0) | 2025.08.30 |
| kube-burner로 쿠버네티스 성능테스트 해보기 (3) | 2025.08.29 |
| [cilium] Mutual Authentication 테스트 해보기 (진행 중) (1) | 2025.08.22 |
