이 글에서는 Cilium을 활용하여 L7(애플리케이션 계층) 수준에서 HTTP 트래픽을 제어하는 방법을 실습합니다. 지금까지 살펴본 L3/L4 정책이 IP와 포트 기반으로 트래픽을 제어했다면, L7 정책은 HTTP 요청의 경로(Path), 호스트(Host), 메서드(Method) 등 더 세부적인 요소를 기반으로 트래픽을 필터링할 수 있습니다. Envoy 프록시를 활용한 이 기능은 Cilium의 가장 강력한 기능 중 하나로, 마이크로서비스 환경에서 세밀한 보안 정책을 구현할 수 있게 합니다.
📌 L7 네트워크 정책의 필요성
✅ L3/L4 정책의 한계
L3/L4 정책만으로는 다음과 같은 세부적인 제어가 불가능합니다:
- 특정 URL 경로(/admin, /api/v1)만 차단하기
- HTTP 메서드(GET, POST, DELETE)별 접근 제어하기
- 특정 호스트(subdomain.example.com)에 대한 요청만 허용하기
- HTTP 헤더 값에 따른 트래픽 필터링하기
✅ L7 정책의 장점
▶️ 더 세밀한 보안: API 엔드포인트 수준의 접근 제어 가능 ▶️ 효율적인 리소스 사용: 필요한 트래픽만 정밀하게 허용 ▶️ 보안 감사 용이성: 애플리케이션 수준의 로깅과 모니터링 가능
📌 L7 정책 동작 원리

✅ Envoy 프록시의 역할
Cilium은 L7 정책을 구현하기 위해 내부적으로 Envoy 프록시를 사용합니다.
[Pod A] → [Cilium eBPF] → [Envoy 프록시] → [Cilium eBPF] → [Pod B]
이 프로세스에서 Envoy 프록시는 다음과 같은 역할을 수행합니다:
- HTTP 요청 내용 검사 (Path, Method, Headers 등)
- 정책 규칙과 비교 평가
- 허용/거부 결정
- 트래픽 로깅 및 모니터링
✅ 성능 고려사항
L7 정책은 L3/L4 정책보다 CPU 및 메모리 사용량이 더 높을 수 있습니다. 모든 요청이 Envoy 프록시를 통과해야 하기 때문입니다. 따라서 실무에서는 정책 적용 범위를 신중하게 결정해야 합니다.
📌 실습 준비: 테스트 환경 구성
✅ 테스트용 네임스페이스 및 애플리케이션 배포
# http-app.yaml
apiVersion: v1
kind: Namespace
metadata:
name: http-test # 테스트를 위한 격리된 네임스페이스 생성
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-server # HTTP 서버 애플리케이션
namespace: http-test # http-test 네임스페이스에 배포
spec:
selector:
matchLabels:
app: http-server # 이 라벨을 가진 Pod를 관리
replicas: 1 # 단일 인스턴스 배포
template:
metadata:
labels:
app: http-server # Pod에 적용되는 라벨 (Cilium 정책에서 참조됨)
spec:
containers:
- name: http-server
image: mendhak/http-https-echo:28 # 테스트에 적합한 에코 서버 이미지 사용
ports:
- containerPort: 8080 # 컨테이너가 수신할 포트
name: http # 포트 이름 지정
---
apiVersion: v1
kind: Service
metadata:
name: http-server # HTTP 서버에 접근하기 위한 서비스
namespace: http-test # http-test 네임스페이스에 배포
spec:
type: ClusterIP # 클러스터 내부에서만 접근 가능
ports:
- port: 8080 # 서비스가 리스닝하는 포트
targetPort: 8080 # 트래픽이 전달될 컨테이너 포트
selector:
app: http-server # 이 라벨을 가진 Pod로 트래픽 전달
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: http-client # HTTP 요청을 테스트할 클라이언트
namespace: http-test # http-test 네임스페이스에 배포
spec:
selector:
matchLabels:
app: http-client # 이 라벨을 가진 Pod를 관리
replicas: 1 # 단일 인스턴스 배포
template:
metadata:
labels:
app: http-client # Pod에 적용되는 라벨 (Cilium 정책에서 참조됨)
spec:
containers:
- name: http-client
image: curlimages/curl:7.80.0 # curl 명령어가 내장된 이미지 사용
command: # 컨테이너가 실행할 명령어
- sleep # 컨테이너를 계속 실행 상태로 유지하는 명령어
- "3600" # 3600초(1시간) 동안 실행
위 매니페스트를 적용합니다:
kubectl apply -f http-app.yaml
✅ 정책 적용 전 연결 테스트
# http-client Pod 이름 가져오기
CLIENT_POD=$(kubectl get pods -n http-test -l app=http-client -o jsonpath='{.items[0].metadata.name}')
# 다양한 경로로 요청 테스트
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/api
kubectl exec -n http-test $CLIENT_POD -- curl -s -X POST http://http-server:8080/admin
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Host: internal.example.com" http://http-server:8080/
모든 요청이 성공적으로 처리되는 것을 확인할 수 있습니다. 이제 L7 정책을 적용하여 어떻게 트래픽이 제어되는지 살펴보겠습니다.
📌 기본 HTTP 경로(Path) 기반 정책

✅ 특정 경로만 허용하는 정책
다음 정책은 / 및 /api 경로만 허용하고 다른 모든 경로는 차단합니다:
# path-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "path-based-policy" # 정책의 이름 (고유해야 함)
namespace: http-test # 정책이 적용될 네임스페이스
spec:
endpointSelector: # 정책이 적용될 대상 Pod 선택
matchLabels:
app: http-server # http-server 라벨을 가진 Pod에만 정책 적용
ingress: # 인바운드 트래픽에 대한 규칙
- fromEndpoints: # 어떤 출발지에서 오는 트래픽을 허용할 것인지 정의
- matchLabels:
app: http-client # http-client 라벨을 가진 Pod에서 오는 트래픽만 허용
toPorts: # 어떤 포트와 프로토콜에 대한 접근을 허용할지 정의
- ports:
- port: "8080" # 8080 포트에 대한 접근 허용
protocol: TCP # TCP 프로토콜 사용
rules: # L7 계층 규칙 시작
http: # HTTP 프로토콜 규칙 정의
- method: "GET" # GET 메서드만 허용 (POST, PUT 등은 차단)
path: "/" # 루트 경로(/)에 대한 요청만 허용
- method: "GET" # 또 다른 허용 규칙 정의
path: "/api" # /api 경로에 대한 GET 요청 허용
# 위에 정의되지 않은 다른 모든 경로는 자동으로 차단됨
정책을 적용합니다:
kubectl apply -f path-policy.yaml
✅ 결과 테스트
# 허용되는 경로
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/api
# 차단되는 경로
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/admin
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/api/v1
허용된 경로(/, /api)는 성공적으로 요청이 처리되지만, 다른 경로(/admin, /api/v1)는 차단됩니다. 차단 시 대개 Connection reset by peer 오류가 발생하거나 요청이 타임아웃됩니다.
주의: 경로 매칭은 정확히 일치하는 경우만 허용됩니다. 예를 들어 /api를 허용해도 /api/v1은 차단됩니다.
📌 HTTP 메서드(Method) 기반 정책
✅ 특정 메서드만 허용하는 정책
다음 정책은 특정 경로에 대해 다른 HTTP 메서드를 허용/차단합니다:
# method-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "method-based-policy" # 정책 이름
namespace: http-test # 적용될 네임스페이스
spec:
endpointSelector: # 정책이 적용될 대상 Pod
matchLabels:
app: http-server # http-server 라벨을 가진 Pod에 적용
ingress: # 인바운드 트래픽 규칙
- fromEndpoints: # 출발지 정의
- matchLabels:
app: http-client # http-client 라벨 Pod에서 오는 트래픽만 허용
toPorts: # 목적지 포트 정의
- ports:
- port: "8080" # 8080 포트 트래픽만 허용
protocol: TCP # TCP 프로토콜만 허용
rules: # L7 규칙 정의 시작
http: # HTTP 프로토콜에 대한 규칙
- method: "GET" # GET 메서드만 허용
path: "/" # 루트 경로에 대해서만 허용
- method: "GET" # GET 메서드만 허용
path: "/api" # /api 경로에 대해서만 허용
- method: "POST" # POST 메서드만 허용
path: "/submit" # /submit 경로에 대해서만 허용 (데이터 제출용)
- method: "PUT" # PUT 메서드만 허용
path: "/update" # /update 경로에 대해서만 허용 (데이터 업데이트용)
- method: "DELETE" # DELETE 메서드만 허용
path: "/delete" # /delete 경로에 대해서만 허용 (데이터 삭제용)
# 위에 명시되지 않은 모든 조합은 차단됨 (예: POST to /api)
기존 정책을 삭제하고 새 정책을 적용합니다:
kubectl delete ciliumnetworkpolicies path-based-policy -n http-test
kubectl apply -f method-policy.yaml
✅ 결과 테스트
# 허용되는 메서드
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/
kubectl exec -n http-test $CLIENT_POD -- curl -s -X POST http://http-server:8080/submit
kubectl exec -n http-test $CLIENT_POD -- curl -s -X PUT http://http-server:8080/update
# 차단되는 메서드
kubectl exec -n http-test $CLIENT_POD -- curl -s -X POST http://http-server:8080/
kubectl exec -n http-test $CLIENT_POD -- curl -s -X DELETE http://http-server:8080/api
허용된 경로+메서드 조합만 성공하고, 그 외의 조합은 차단됩니다. 이렇게 메서드 기반 정책을 사용하면 읽기 작업(GET)과 쓰기 작업(POST, PUT, DELETE)을 세밀하게 제어할 수 있습니다.
📌 호스트(Host) 헤더 기반 정책
✅ 특정 호스트만 허용하는 정책
다음 정책은 특정 Host 헤더 값을 가진 요청만 허용합니다:
# host-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "host-based-policy" # 정책 이름
namespace: http-test # 적용될 네임스페이스
spec:
endpointSelector: # 정책이 적용될 대상 Pod
matchLabels:
app: http-server # http-server 라벨을 가진 Pod에 적용
ingress: # 인바운드 트래픽 규칙
- fromEndpoints: # 출발지 정의
- matchLabels:
app: http-client # http-client 라벨 Pod에서 오는 트래픽만 허용
toPorts: # 목적지 포트 정의
- ports:
- port: "8080" # 8080 포트 트래픽만 허용
protocol: TCP # TCP 프로토콜만 허용
rules: # L7 규칙 정의 시작
http: # HTTP 프로토콜에 대한 규칙
- method: "GET" # GET 메서드 허용
path: "/" # 루트 경로(/)에 대한 요청
host: "api.example.com" # Host 헤더가 api.example.com인 요청만 허용
# 다른 Host 헤더 값은 차단됨
- method: "GET" # GET 메서드 허용
path: "/admin" # /admin 경로에 대한 요청
host: "internal.example.com" # Host 헤더가 internal.example.com인 요청만 허용
# 다른 Host 헤더 값은 차단됨
기존 정책을 삭제하고 새 정책을 적용합니다:
kubectl delete ciliumnetworkpolicies method-based-policy -n http-test
kubectl apply -f host-policy.yaml
✅ 결과 테스트
# 허용되는 호스트 헤더
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Host: api.example.com" http://http-server:8080/
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Host: internal.example.com" http://http-server:8080/admin
# 차단되는 호스트 헤더
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/ # Host 헤더 없음
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Host: external.example.com" http://http-server:8080/
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Host: api.example.com" http://http-server:8080/admin # 경로 불일치
이 정책은 다중 도메인 환경에서 가상 호스팅 시나리오에 유용합니다. 동일한 서비스에 여러 도메인이 접근할 때 도메인별로 다른 접근 규칙을 적용할 수 있습니다.
📌 패턴 매칭을 사용한 고급 HTTP 정책
✅ 정규식 패턴을 이용한 경로 매칭
Cilium은 정규식 패턴을 사용하여 더 유연한 경로 매칭을 지원합니다:
# pattern-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "pattern-based-policy" # 정책 이름
namespace: http-test # 적용될 네임스페이스
spec:
endpointSelector: # 정책이 적용될 대상 Pod
matchLabels:
app: http-server # http-server 라벨을 가진 Pod에 적용
ingress: # 인바운드 트래픽 규칙
- fromEndpoints: # 출발지 정의
- matchLabels:
app: http-client # http-client 라벨 Pod에서 오는 트래픽만 허용
toPorts: # 목적지 포트 정의
- ports:
- port: "8080" # 8080 포트 트래픽만 허용
protocol: TCP # TCP 프로토콜만 허용
rules: # L7 규칙 정의 시작
http: # HTTP 프로토콜에 대한 규칙
- method: "GET" # GET 메서드 허용
path: "/api/v[0-9]+" # 정규식 패턴: /api/v1, /api/v2, /api/v999 등 모든 API 버전 허용
# 숫자가 포함된 모든 API 버전 경로가 허용됨
# 예: /api/v1, /api/v2는 허용되지만 /api/version은 차단됨
- method: "GET" # GET 메서드 허용
path: "/user/[0-9]+" # 정규식 패턴: /user/123, /user/456 등 숫자 기반 사용자 ID 허용
# 예: /user/123은 허용되지만 /user/admin은 차단됨
- method: "GET" # GET 메서드 허용
path: "/health" # 정확한 경로 매칭: /health 경로만 정확히 허용
- method: "GET" # GET 메서드 허용
path: "/" # 루트 경로(/) 정확히 허용
기존 정책을 삭제하고 새 정책을 적용합니다:
kubectl delete ciliumnetworkpolicies host-based-policy -n http-test
kubectl apply -f pattern-policy.yaml
✅ 결과 테스트
# 허용되는 패턴 경로
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/api/v1
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/api/v2
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/user/123
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/health
# 차단되는 패턴 경로
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/api
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/api/version
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/user/admin
정규식 패턴을 사용하면 모든 API 엔드포인트나 사용자 ID를 일일이 나열하지 않고도 유연하게 접근을 제어할 수 있습니다.
📌 복합 정책: 여러 조건 조합하기
✅ 메서드, 경로, 호스트를 조합한 정책
실제 프로덕션 환경에서는 여러 조건을 조합하여 더 복잡한 정책을 구성할 수 있습니다:
# complex-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "complex-http-policy" # 정책 이름
namespace: http-test # 적용될 네임스페이스
spec:
endpointSelector: # 정책이 적용될 대상 Pod
matchLabels:
app: http-server # http-server 라벨을 가진 Pod에 적용
ingress: # 인바운드 트래픽 규칙
- fromEndpoints: # 출발지 정의
- matchLabels:
app: http-client # http-client 라벨 Pod에서 오는 트래픽만 허용
toPorts: # 목적지 포트 정의
- ports:
- port: "8080" # 8080 포트 트래픽만 허용
protocol: TCP # TCP 프로토콜만 허용
rules: # L7 규칙 정의 시작
http: # HTTP 프로토콜에 대한 규칙
# 공개 API - 모든 호스트에서 접근 가능
- method: "GET" # GET 메서드만 허용
path: "/api/public" # /api/public 경로만 허용
# Host 헤더 제한 없음 (모든 호스트에서 접근 가능)
# 내부 API - 특정 호스트만 접근 가능
- method: "GET" # GET 메서드만 허용
path: "/api/internal" # /api/internal 경로만 허용
host: "internal.example.com" # internal.example.com 호스트만 허용
# 다른 호스트에서는 이 경로에 접근 불가
# 관리자 API - 특정 호스트만 POST, PUT, DELETE 가능
- method: "GET" # GET 메서드 허용 (읽기 접근)
path: "/admin/.*" # 정규식으로 모든 admin 하위 경로 매칭 (/admin/users, /admin/settings 등)
host: "admin.example.com" # admin.example.com 호스트만 허용
- method: "POST" # POST 메서드 허용 (생성 작업)
path: "/admin/.*" # 모든 admin 하위 경로에 대해
host: "admin.example.com" # admin.example.com 호스트만 허용
- method: "PUT" # PUT 메서드 허용 (수정 작업)
path: "/admin/.*" # 모든 admin 하위 경로에 대해
host: "admin.example.com" # admin.example.com 호스트만 허용
- method: "DELETE" # DELETE 메서드 허용 (삭제 작업)
path: "/admin/.*" # 모든 admin 하위 경로에 대해
host: "admin.example.com" # admin.example.com 호스트만 허용
# 헬스체크 엔드포인트 - 모든 호스트에서 접근 가능
- method: "GET" # GET 메서드만 허용
path: "/health" # /health 경로만 허용
# Host 헤더 제한 없음 (모니터링 시스템에서 자유롭게 접근 가능)
# 모니터링 엔드포인트 - 특정 호스트만 접근 가능
- method: "GET" # GET 메서드만 허용
path: "/metrics" # /metrics 경로만 허용 (프로메테우스 등 모니터링 시스템용)
host: "monitoring.example.com" # monitoring.example.com 호스트만 허용
# 다른 호스트에서는 메트릭 접근 불가
기존 정책을 삭제하고 새 정책을 적용합니다:
kubectl delete ciliumnetworkpolicies pattern-based-policy -n http-test
kubectl apply -f complex-policy.yaml
✅ 복합 정책 테스트
# 공개 API - 모든 호스트 허용
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/api/public
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Host: any.example.com" http://http-server:8080/api/public
# 내부 API - 특정 호스트만 허용
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Host: internal.example.com" http://http-server:8080/api/internal
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/api/internal # 차단됨
# 관리자 API - 특정 호스트만 허용
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Host: admin.example.com" http://http-server:8080/admin/users
kubectl exec -n http-test $CLIENT_POD -- curl -s -X POST -H "Host: admin.example.com" http://http-server:8080/admin/users
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Host: other.example.com" http://http-server:8080/admin/users # 차단됨
# 헬스체크 - 모든 호스트 허용
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/health
# 모니터링 - 특정 호스트만 허용
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Host: monitoring.example.com" http://http-server:8080/metrics
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/metrics # 차단됨
이러한 복합 정책을 통해 마이크로서비스 환경에서 다양한 접근 시나리오
📌 HTTP 헤더 기반 정책
✅ 특정 HTTP 헤더 값을 기반으로 한 정책
Cilium은 Host 헤더 외에도 다른 HTTP 헤더를 기반으로 트래픽을 필터링할 수 있습니다:
# header-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "header-based-policy" # 정책 이름
namespace: http-test # 적용될 네임스페이스
spec:
endpointSelector: # 정책이 적용될 대상 Pod
matchLabels:
app: http-server # http-server 라벨을 가진 Pod에 적용
ingress: # 인바운드 트래픽 규칙
- fromEndpoints: # 출발지 정의
- matchLabels:
app: http-client # http-client 라벨 Pod에서 오는 트래픽만 허용
toPorts: # 목적지 포트 정의
- ports:
- port: "8080" # 8080 포트 트래픽만 허용
protocol: TCP # TCP 프로토콜만 허용
rules: # L7 규칙 정의 시작
http: # HTTP 프로토콜에 대한 규칙
# API 키가 있는 요청만 허용
- method: "GET" # GET 메서드 허용
path: "/api/.*" # 모든 API 경로에 대해 정규식 매칭
headers: # 헤더 기반 필터링 시작
- 'X-API-Key: [a-zA-Z0-9]+' # X-API-Key 헤더가 영문자/숫자로만 구성되어야 함
# 예: X-API-Key: abc123은 허용, X-API-Key: abc-123은 차단
# 특정 사용자 에이전트만 허용
- method: "GET" # GET 메서드 허용
path: "/compatibility" # /compatibility 경로에 대해서만
headers: # 헤더 기반 필터링 시작
- 'User-Agent: Mozilla.*' # Mozilla로 시작하는 User-Agent만 허용
# 예: User-Agent: Mozilla/5.0은 허용
# Chrome이나 Safari 등은 차단됨
# 특정 Content-Type만 허용
- method: "POST" # POST 메서드 허용
path: "/data" # /data 경로에 대해서만
headers: # 헤더 기반 필터링 시작
- 'Content-Type: application/json' # JSON 요청만 허용
# text/plain, form-data 등은 차단됨
# 특정 Accept 헤더가 있는 요청만 허용
- method: "GET" # GET 메서드 허용
path: "/docs" # /docs 경로에 대해서만
headers: # 헤더 기반 필터링 시작
- 'Accept: text/html' # HTML 응답을 요청하는 클라이언트만 허용
# Accept: application/json은 차단됨
기존 정책을 삭제하고 새 정책을 적용합니다:
kubectl delete ciliumnetworkpolicies complex-http-policy -n http-test
kubectl apply -f header-policy.yaml
✅ 헤더 기반 정책 테스트
# API 키 헤더 테스트
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "X-API-Key: abc123" http://http-server:8080/api/users
kubectl exec -n http-test $CLIENT_POD -- curl -s http://http-server:8080/api/users # 차단됨 (API 키 없음)
# User-Agent 헤더 테스트
kubectl exec -n http-test $CLIENT_POD -- curl -s -A "Mozilla/5.0" http://http-server:8080/compatibility
kubectl exec -n http-test $CLIENT_POD -- curl -s -A "Chrome/90.0" http://http-server:8080/compatibility # 차단됨
# Content-Type 헤더 테스트
kubectl exec -n http-test $CLIENT_POD -- curl -s -X POST -H "Content-Type: application/json" -d '{}' http://http-server:8080/data
kubectl exec -n http-test $CLIENT_POD -- curl -s -X POST -H "Content-Type: text/plain" -d 'text' http://http-server:8080/data # 차단됨
# Accept 헤더 테스트
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Accept: text/html" http://http-server:8080/docs
kubectl exec -n http-test $CLIENT_POD -- curl -s -H "Accept: application/json" http://http-server:8080/docs # 차단됨
헤더 기반 정책은 API 키 검증, 사용자 에이전트 제한, 콘텐츠 타입 필터링 등 애플리케이션 수준의 보안을 강화하는 데 매우 유용합니다.
📌 Hubble을 활용한 L7 정책 모니터링

✅ L7 정책 로그 확인
Hubble을 사용하여 L7 정책의 허용/거부 결정을 모니터링할 수 있습니다:
# Hubble CLI 사용
hubble observe --namespace http-test --protocol http
# 특정 HTTP 상태 코드 필터링
hubble observe --namespace http-test --protocol http --http-status 403
✅ 거부된 HTTP 요청 분석
Hubble UI에서는 L7 정책에 의해 거부된 요청을 시각적으로 확인할 수 있습니다. Hubble UI에 접속하여 다음 필터를 적용하세요:
namespace http-test and verdict DROPPED
이를 통해 어떤 요청이 왜 거부되었는지 분석할 수 있습니다.
📌 실무 적용 사례 및 팁
✅ API 게이트웨이 보안 강화
# api-gateway-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "api-gateway-policy" # 정책 이름
namespace: production # 프로덕션 네임스페이스에 적용
spec:
endpointSelector: # 정책이 적용될 대상 Pod
matchLabels:
app: api-gateway # api-gateway 라벨을 가진 Pod에 적용
ingress: # 인바운드 트래픽 규칙
- fromEndpoints: # 출발지 정의
- matchLabels: {} # 빈 매치레이블은 모든 소스 허용 (ingress로부터 오는 트래픽 포함)
# 인그레스 컨트롤러나 외부 로드밸런서에서 오는 트래픽 허용
toPorts: # 목적지 포트 정의
- ports:
- port: "8080" # 8080 포트 트래픽만 허용
protocol: TCP # TCP 프로토콜만 허용
rules: # L7 규칙 정의 시작
http: # HTTP 프로토콜에 대한 규칙
# 인증 API는 모든 메서드 허용 (로그인/회원가입 필요)
- method: "GET|POST" # GET 또는 POST 메서드 허용 (정규식 사용)
path: "/auth/.*" # /auth로 시작하는 모든 경로 허용 (/auth/login, /auth/register 등)
# 사용자 API는 인증된 요청만 허용 (JWT 토큰 필요)
- method: "GET|POST|PUT|DELETE" # 모든 주요 HTTP 메서드 허용
path: "/api/users/.*" # /api/users로 시작하는 모든 경로 허용
headers: # 헤더 기반 필터링
- 'Authorization: Bearer .*' # Bearer 토큰이 있는 요청만 허용 (JWT 인증용)
# 인증 헤더가 없는 요청은 차단됨
# 버전 및 상태 확인 엔드포인트 허용 (모니터링용)
- method: "GET" # GET 메서드만 허용
path: "/api/version" # /api/version 경로만 허용 (버전 정보 확인용)
- method: "GET" # GET 메서드만 허용
path: "/healthz" # /healthz 경로만 허용 (쿠버네티스 liveness/readiness 프로브용)
# 쿠버네티스 상태 체크에 필수적인 경로
✅ 마이크로서비스 접근 제어
# microservice-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "payment-service-policy" # 정책 이름
namespace: production # 프로덕션 네임스페이스에 적용
spec:
endpointSelector: # 정책이 적용될 대상 Pod
matchLabels:
app: payment-service # payment-service 라벨을 가진 Pod에 적용 (결제 서비스)
ingress: # 인바운드 트래픽 규칙
- fromEndpoints: # 출발지 정의
- matchLabels:
app: order-service # order-service 라벨 Pod에서 오는 트래픽만 허용
# 결제 서비스는 주문 서비스에서만 호출 가능
# 다른 서비스에서는 직접 결제 서비스 호출 불가
toPorts: # 목적지 포트 정의
- ports:
- port: "8080" # 8080 포트 트래픽만 허용
protocol: TCP # TCP 프로토콜만 허용
rules: # L7 규칙 정의 시작
http: # HTTP 프로토콜에 대한 규칙
# 결제 처리 API (POST만 허용)
- method: "POST" # POST 메서드만 허용 (새 결제 생성용)
path: "/api/payments" # /api/payments 경로만 허용
headers: # 헤더 기반 필터링
- 'Content-Type: application/json' # JSON 형식의 요청만 허용
# 다른 형식은 차단됨
- 'X-Transaction-ID: [a-f0-9-]+' # 트랜잭션 ID 형식 검증 (UUID 형식)
# 요청 추적 및 중복 방지용
# 결제 상태 조회 API (GET만 허용)
- method: "GET" # GET 메서드만 허용 (결제 상태 조회용)
path: "/api/payments/[a-f0-9-]+" # UUID 형식의 결제 ID 패턴만 허용
# 예: /api/payments/123e4567-e89b-12d3-a456-426614174000
✅ 실무 적용 팁
- 점진적 적용: 먼저 모니터링 모드로 정책을 적용하여 정책의 영향을 분석한 후, 실제 적용합니다.
- 기본 거부 정책: 기본적으로 모든 트래픽을 거부하고, 필요한 경로만 명시적으로 허용하는 방식을 권장합니다.
- 정규식 최적화: 복잡한 정규식은 성능에 영향을 줄 수 있으므로, 가능한 간단하게 유지하세요.
- 경로 그룹화: 유사한 경로는 정규식으로 그룹화하여 정책 관리를 간소화하세요.
- 헬스체크 허용: 모니터링 및 헬스체크 엔드포인트는 항상 허용하여 시스템 상태 확인이 가능하게 하세요.
- 배포 전 테스트: 새로운 정책은 반드시 테스트 환경에서 검증한 후 프로덕션에 적용하세요.
- 점진적 확장: 간단한 정책으로 시작하여 점차 세밀한 규칙을 추가하는 방식으로 접근하세요.
- Hubble 활용: 정책 적용 후 Hubble을 통해 트래픽 흐름을 모니터링하여 의도치 않은 차단이 없는지 확인하세요.
📌 추가 고려사항: L7 정책 성능 최적화
✅ L7 정책 부하 분산
L7 정책은 추가적인 CPU 및 메모리 리소스를 소비합니다. 다음과 같은 방법으로 성능을 최적화할 수 있습니다:
# optimized-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "optimized-l7-policy" # 정책 이름
namespace: production # 프로덕션 네임스페이스에 적용
spec:
endpointSelector: # 정책이 적용될 대상 Pod
matchLabels:
app: api-service # api-service 라벨을 가진 Pod에 적용
ingress: # 인바운드 트래픽 규칙
# L3/L4 규칙: 모니터링 시스템의 헬스체크는 L7 검사 없이 빠르게 처리
- fromEndpoints: # 출발지 정의
- matchLabels:
app: monitoring # monitoring 라벨을 가진 Pod에서 오는 트래픽
toPorts: # 목적지 포트 정의
- ports:
- port: "8080" # 8080 포트
protocol: TCP # TCP 프로토콜
# L7 rules 섹션이 없음 = L3/L4 레벨에서만 필터링 (더 빠름)
# L7 규칙: 일반 클라이언트 요청만 세밀하게 검사
- fromEndpoints: # 출발지 정의
- matchLabels:
app: frontend # frontend 라벨을 가진 Pod에서 오는 트래픽
toPorts: # 목적지 포트 정의
- ports:
- port: "8080" # 8080 포트
protocol: TCP # TCP 프로토콜
rules: # L7 규칙 정의 시작 (세밀한 검사 적용)
http: # HTTP 프로토콜에 대한 규칙
- method: "GET" # GET 메서드만 허용
path: "/api/.*" # /api로 시작하는 모든 경로
- method: "POST" # POST 메서드만 허용
path: "/api/submit" # /api/submit 경로만
이 정책은 모니터링 시스템에서의 헬스체크 요청은 L3/L4 레벨에서만 빠르게 처리하고, 일반 사용자 요청만 L7 레벨에서 세밀하게 검사합니다.
📌 Summary
이번 글에서는 Cilium의 L7 HTTP 정책 기능을 다양한 시나리오로 살펴보았습니다.
✅ L7 정책의 주요 특징:
- Envoy 프록시를 활용하여, HTTP 요청의 경로(Path), 메서드(Method), 호스트(Host), 헤더(Headers) 기반 필터링 가능
- 애플리케이션 수준의 세밀한 보안 제어 제공
- L3/L4 정책보다 CPU 및 메모리 사용량 증가
✅ 학습한 정책 유형:
- 경로(Path) 기반 정책: 특정 URL 경로만 허용/차단
- 메서드(Method) 기반 정책: GET, POST, PUT, DELETE 등 메서드별 제어
- 호스트(Host) 헤더 기반 정책: 특정 도메인에 대한 요청만 허용
- 정규식 패턴 매칭: 다양한 경로 패턴을 유연하게 제어
- HTTP 헤더 기반 정책: API 키, 사용자 에이전트, 컨텐츠 타입 등 검증
- 복합 정책: 여러 조건을 조합한 실전 시나리오
✅ 실무 적용 시 고려사항:
- 점진적 접근: 모니터링 모드 → 테스트 → 프로덕션 적용
- 성능 최적화: 필요한 경우에만 L7 정책 적용
- Hubble을 활용한 모니터링과 디버깅
- 최소 권한 원칙: 기본 거부, 필요한 경로만 명시적 허용
'Kubernetes Tools > Cilium' 카테고리의 다른 글
EP10. CIDR, Entity 기반 정책 구성 | 외부 접근 정밀 제어 (0) | 2025.03.22 |
---|---|
EP09. L7 정책 실습 (Kafka, DNS 등) | HTTP 요청이 아닌 트래픽 제어 (0) | 2025.03.22 |
EP07. Cilium vs Kubernetes NetworkPolicy 비교 | 동작 차이 완벽 이해 (0) | 2025.03.22 |
EP06. 기본 L3/L4 정책 설정 | CiliumNetworkPolicy 기초 실습 (0) | 2025.03.22 |
EP05. Hubble 설치 및 구성 | 쿠버네티스 네트워크 가시성 확보 (0) | 2025.03.22 |