cilium 공식문서의 secureing gRPC 파트를 보면 gRPC-aware한 보안 정책을 제공하여 gRPC 기반 마이크로서비스의 보안을 강화할 수 있다.
Layer 7 수준에서 gRPC 호출을 인식하고, gRPC 메서드를 HTTP URL 형태(예: /package.Service/Method)로 매핑하여 정책을 적용하고 특정 메서드는 차단하고, 필요한 메서드만 허용할 수 있다.
정책이 whitelist 기반이므로, 명시적으로 허용(Explicit allow)된 메서드만 통과되고 나머지는 암묵적으로 거부(Implicit deny)되는 특성이 있다.
https://github.com/ryusstory/k8s-3tier-sample-clickcounter/tree/cni/cilium
https://ryusstory.tistory.com/entry/k8s-%ED%85%8C%EC%8A%A4%ED%8A%B8%EC%9A%A9-3tier-sample-app
기존 글은 kindnet으로 작성되었으나 cilium cni를 적용해서 진행했다.
구성은 kind 구성시에 kindnet CNI를 비활성화 시키고, kubeproxy를 사용하지 않는 옵션으로 배포 했다.
networking:
disableDefaultCNI: true
kubeProxyMode: "none"
helm install cilium cilium/cilium --version 1.18.1 \
--namespace kube-system \
--set kubeProxyReplacement=true \
--set nodePort.enabled=true \
--set ingressController.enabled=true \
--set ingressController.loadbalancerMode=dedicated \
--set ingressController.hostNetwork.enabled=true \
--set ingressController.hostNetwork.sharedListenerPort=8080 \
--set k8sServiceHost=${API_SERVER_IP} \
--set k8sServicePort=${API_SERVER_PORT} \
--set bpf.masquerade=true \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set operator.replicas=1
cilium ingress를 사용하기위해 필수조건에 언급된 대로 kubeProxyReplacement=true 와 nodePort.enabled=true 사용하고,
ingress를 설치하기 위해 --set ingressController.enabled=true와 ingressController.loadbalancerMode=dedicated를 사용했다.
hostnetwork 모드는 Cilium Ingress Controller를 호스트 네트워크에 직접 노출시켜 유용하게 사용할 수 있다.
기존처럼 Service type을 nodeport로 열어도 접근이 가능하지만 ingress를 사용해보기 위해 사용했다.
기존 nodeport에서 clusterIP로 바꾸고 ingress를 통해 들어오도록 구성했다.
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: frontend
ports:
- port: 3000
targetPort: 3000
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: click
annotations:
ingress.cilium.io/loadbalancer-mode: dedicated
spec:
ingressClassName: cilium
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 3000
cilium hubble ui와 port-forward 명령어로 웹과 hubble observe 를 준비한다.
cilium hubble ui &
cilium hubble port-forward &
hubble ui를 열고 backend-grpc 를 눌러서 보면 이렇게 정상적으로 grpc 통신이 이뤄지는 걸 볼 수 있고, click.proto에서 정의한 메소드 명도 볼 수 있다.
service ClickService {
rpc GetClicks(Empty) returns (ClicksResponse) {}
rpc AddClick(AddClickRequest) returns (AddClickResponse) {}
}

hubble observe 를 통해 보면 현재는 정상적으로 FORWARDED 상태로 통신되는 걸 볼 수 있다.
ryuss@R250822:/mnt/d/study/kind-git$ hubble observe -f --from-label app=frontend --to-label app=backend-grpc
Sep 5 11:13:14.892: default/frontend-74647b95d9-ckfpc:52198 (ID:8739) -> default/backend-grpc-6955f774c9-qtqzf:50051 (ID:20261) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Sep 5 11:13:15.171: default/frontend-74647b95d9-wgj9w:53284 (ID:8739) -> default/backend-grpc-6955f774c9-qtqzf:50051 (ID:20261) to-overlay FORWARDED (TCP Flags: ACK, PSH)
Sep 5 11:13:15.172: default/frontend-74647b95d9-wgj9w:53284 (ID:8739) -> default/backend-grpc-6955f774c9-qtqzf:50051 (ID:20261) to-endpoint FORWARDED (TCP Flags: ACK, PSH)
Sep 5 11:13:22.634: default/frontend-74647b95d9-wgj9w:53284 (ID:8739) -> default/backend-grpc-6955f774c9-qtqzf:50051 (ID:20261) to-overlay FORWARDED (TCP Flags: ACK, PSH)
Sep 5 11:13:22.634: default/frontend-74647b95d9-wgj9w:53284 (ID:8739) -> default/backend-grpc-6955f774c9-qtqzf:50051 (ID:20261) to-endpoint FORWARDED (TCP Flags: ACK, PSH)

위 그림과 같은 구성에서 AddClick만 허용하는 정책을 넣어보려고 한다. 정책이 없을 때는 default allow 정책이지만 하나라도 정책을 넣게 되면 해당 정책 외에는 default deny 정책이 적용된다. implicit deny(암묵적 거부)라고 표현하기도 한다.
그래서 AddClick을 허용하는 순간 GetClicks는 막혀야한다.

app:frontend 에서 app:backend-grpc 로 가는 AddClick만 허용하는 cnp-grpc.yaml 파일을 만들어서 kubectl apply -f cnp-grpc.yaml로 적용했다.
적용하면 GetClicks는 자동으로 차단될것으로 예상된다.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: restrict-grpc-getclicks
spec:
description: allow only addclick grpc method from frontend to backend-grpc
endpointSelector:
matchLabels:
app: backend-grpc
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "50051"
protocol: TCP
rules:
http:
- method: "POST"
path: "/click.ClickService/AddClick"
적용하면 hubble ui나 hubble observe에서 바로 DROPPED 로그나 UI에서도 바로 막히는 걸 볼 수 있다.

막히는 걸 확인했으니, 이제 GetClicks도 허용하여 다시 정상 통신을 복구해보자.

앞에서 만든 rules에다가 GetClicks도 추가를 해줬다.
rules:
http:
- method: "POST"
path: "/click.ClickService/AddClick"
- method: "POST"
path: "/click.ClickService/GetClicks"
적용하고 나서 GetClicks 호출도 정상적으로 FORWARDED로 허용되면서 정상적으로 통신하는 걸 확인할 수 있다
_참고: 처음에는 hubble observe에서 메서드명이 안 보이기도 하지만, 일정 시간 이후 메서드명까지 표시되었다

| Cilium Policy Audit Mode로 네트워크 정책 만들기 (0) | 2025.09.06 |
|---|---|
| K8s 테스트용 3tier sample (0) | 2025.09.05 |
| kube-burner measurement 테스트 (1) | 2025.08.30 |