본문 바로가기
IT적응기

쿠버네티스 NetworkPolicy (CNI, deny-all, 트래픽제어)

by IT적응기 2026. 6. 20.

쿠버네티스 NetworkPolicy (CNI, deny-all, 트래픽제어)
쿠버네티스 NetworkPolicy

쿠버네티스 클러스터는 기본 상태에서 모든 파드가 서로 자유롭게 통신할 수 있는 'all allow' 구조로 동작합니다. 처음에는 "어차피 내부 네트워크인데 뭐가 문제야"라고 생각했는데, 보안 감사에서 DB 파드가 프론트엔드 파드에 그대로 노출되어 있다는 지적을 받은 뒤로 생각이 완전히 바뀌었습니다. 그 지적을 받던 순간의 민망함이 지금도 생생합니다. "쿠버네티스 쓰면 보안은 알아서 된다"는 막연한 믿음이 만든 구멍이었습니다.

팩트 확인: NetworkPolicy와 CNI의 관계

일반적으로 NetworkPolicy YAML 파일을 클러스터에 적용하면 곧바로 트래픽이 차단될 거라고 생각하는 분들이 많습니다. 저도 처음에는 그렇게 믿었습니다. 그런데 실제로 써보니 전혀 그렇지 않았습니다.

NetworkPolicy는 쿠버네티스 리소스 명세일 뿐이고, 실제 트래픽 제어는 CNI(Container Network Interface) 플러그인이 담당합니다. CNI란 컨테이너가 네트워크에 연결될 때 IP 할당, 라우팅, 정책 집행 등을 처리하는 인터페이스 표준입니다. 쉽게 말해, NetworkPolicy는 '규칙서'고 CNI는 그 규칙을 실제로 집행하는 '경비원'인 셈입니다.

문제는 모든 CNI가 NetworkPolicy를 지원하지 않는다는 점입니다. 제가 운영하던 EKS 클러스터에는 기본으로 aws-vpc-cni가 설치되어 있었는데, 이 플러그인은 기본 설정 상태에서 NetworkPolicy를 지원하지 않습니다. NetworkPolicy YAML을 적용해도 트래픽이 전혀 차단되지 않았고, 한동안 원인을 못 찾아 꽤 오랜 시간을 소비했습니다. 설정이 무시되고 있는데 에러 메시지조차 없으니 찾기가 더 어려웠습니다. NetworkPolicy를 집행하려면 Calico, Cilium, Kube-router 같은 플러그인을 설치하거나, Amazon VPC CNI의 네트워크 정책 기능을 별도로 활성화해야 합니다. 이 사실을 공식 문서 어딘가에서 읽었던 것 같은데, 실제로 부딪히기 전까지 그게 어떤 의미인지 체감하지 못했습니다.

NetworkPolicy가 적용되면 동작 방식이 완전히 달라집니다. 정책이 없는 파드는 모든 트래픽이 허용되지만, NetworkPolicy가 하나라도 적용된 파드는 나머지 트래픽이 전부 차단(default-deny)되고 정책에서 명시적으로 허용한 경로만 통과하게 됩니다. 여기서 default-deny란 "명시적으로 허용하지 않은 모든 연결을 자동으로 거부"하는 보안 원칙을 뜻합니다.

NetworkPolicy가 지원하는 정책 유형을 정리하면 다음과 같습니다. Ingress(수신)는 파드로 들어오는 트래픽을 제어하고, Egress(송신)는 파드에서 나가는 트래픽을 제어합니다. podSelector는 레이블 기반으로 특정 파드 그룹에만 정책을 적용하고, namespaceSelector는 다른 네임스페이스의 파드를 허용하거나 제한할 때 사용합니다. ipBlock은 외부 IP 대역을 기준으로 트래픽을 제어합니다.

policyTypes를 명시하지 않으면 Egress 규칙이 무시되는 경우가 있다는 점도 직접 겪고 나서야 알았습니다. Egress를 제어하려고 정책을 적용했는데 아무 변화가 없어서 한참 헤맨 적이 있습니다. 이후로는 반드시 policyTypes 항목에 Ingress와 Egress를 명시적으로 선언하는 습관을 들였습니다.

경험과 의견: deny-all 기본 정책이 왜 필요한가

NetworkPolicy 실전 도입 초기에 가장 많이 한 실수는 필요한 경로만 골라서 허용 정책을 추가하는 방식으로 접근한 것입니다. 언뜻 보면 합리적인 방법 같지만, 새 파드가 배포될 때마다 정책 공백이 생겨 의도치 않게 포트가 열리는 상황이 반복됐습니다. 특히 개발 팀에서 빠르게 파드를 추가하는 환경에서는 이 공백이 눈 깜짝할 사이에 생겼습니다.

여러 번 시행착오를 겪은 끝에 정착한 방식은, 네임스페이스 단위로 모든 트래픽을 차단하는 deny-all 기본 정책을 먼저 깔고, 그 위에 필요한 통신 경로만 화이트리스트로 열어주는 구조입니다. 화이트리스트(whitelist)란 명시적으로 허용한 항목만 통과시키고 나머지는 모두 거부하는 접근 제어 방식을 말합니다. 이 구조를 적용하고 나서 보안 감사 때 "어떤 파드가 어떤 파드와 통신하는가"를 훨씬 명확하게 설명할 수 있었고, 감사 지적 항목도 크게 줄었습니다.

솔직히 이건 예상 밖이었습니다. YAML 파일 몇 개를 추가하는 것으로 이렇게 큰 차이가 날 거라고 생각하지 못했습니다. 특히 ingress 규칙만 작성하고 egress를 빠뜨리는 실수, 레이블 셀렉터를 잘못 지정해서 엉뚱한 파드에 정책이 걸리는 실수를 반복했는데, 이 두 가지는 트래픽 시각화 도구를 쓰기 전까지는 원인을 찾기가 정말 어렵습니다. 정책이 적용됐는데 트래픽이 왜 막히는지 모르겠다는 상황과, 정책이 왜 동작 안 하는지 모르겠다는 상황을 번갈아 겪었습니다. 둘 다 가시성 부재에서 오는 문제였습니다.

제 경험상 Cilium의 Hubble이나 Istio 기반 환경에서 사용하는 Kiali 같은 시각화 도구를 병행하지 않으면, 정책이 의도대로 동작하는지 검증하기가 상당히 까다롭습니다. Hubble이란 Cilium 위에서 동작하는 네트워크 가시성 도구로, 파드 간 트래픽 흐름을 실시간으로 확인할 수 있어 정책 디버깅에 실질적인 도움을 줍니다. Hubble을 처음 켰을 때 그동안 보이지 않던 트래픽 흐름이 한눈에 들어오는 걸 보고, 왜 진작 쓰지 않았나 싶었습니다.

한 가지 더 짚어두고 싶은 것은 NetworkPolicy의 한계입니다. NetworkPolicy는 파드 수준의 트래픽만 제어할 수 있고, 노드 수준 트래픽은 통제 범위 밖입니다. 또한 명시적인 deny 규칙을 선언할 수 없고 허용 규칙만 추가하는 구조라, 복잡한 정책이 필요할 때는 Cilium의 CiliumNetworkPolicy 같은 확장 리소스에 의존해야 합니다. "이 특정 파드에서 저 파드로 가는 트래픽만 명시적으로 차단하고 싶다"는 요구사항이 생겼을 때, 기본 NetworkPolicy로는 구현이 안 된다는 걸 뒤늦게 알았습니다. NetworkPolicy 하나로 컨테이너 보안이 완성된다는 생각은 위험합니다. mTLS(상호 TLS 인증), RBAC(역할 기반 접근 제어), Pod Security Admission 등 다층적 보안 레이어와 함께 운영될 때 비로소 의미 있는 방어 체계가 됩니다.

NetworkPolicy 도입을 미루고 있다면, 지금 당장 자신의 클러스터에서 DB 파드가 어떤 파드와 통신 가능한 상태인지 먼저 확인해 보시길 권합니다. 저처럼 보안 감사 지적을 받고 나서야 부랴부랴 대응하는 상황만큼은 피하는 게 좋습니다. deny-all 기본 정책을 먼저 깔고, 필요한 경로를 하나씩 열어가는 방식으로 시작하는 것이 가장 현실적인 출발점입니다. 그리고 반드시 시각화 도구를 함께 켜두세요. 눈에 보이지 않으면 고칠 수가 없습니다.


참고:


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 깜짝,황금이 아빠 IT적응기

서치어드바이저