본문 바로가기
클라우드/Cilium

🚨 내 클러스터는 내가 지킨다! Cilium 네트워크 정책, 이것만 알면 끝!

by gasbugs 2025. 12. 5.

안녕하세요! 쿠버네티스 환경에서 복잡하게 얽힌 서비스들의 통신을 보며 골치 아팠던 경험, 다들 한 번쯤 있으시죠? 🧐 "이 파드는 저 파드랑 통신해야 하는데...", "어? 이 파드는 절대 외부로 나가면 안 되는데!" 와 같은 고민들 말이에요.

오늘은 바로 이 복잡한 네트워크 트래픽을 명쾌하게 정리해 줄 해결사, Cilium 네트워크 정책의 핵심 원리에 대해 알아보려고 합니다. 마치 교통정리 경찰관처럼, 어떤 트래픽을 보내고(Go🚦), 어떤 트래픽을 막을지(Stop🛑) 결정하는 아주 간단하면서도 강력한 규칙이죠.

이 글만 끝까지 읽으시면, 여러분도 Cilium 네트워크 정책 전문가가 될 수 있습니다!


🤔 Cilium 정책, 그래서 핵심이 뭔데?

결론부터 말씀드릴게요. Cilium 네트워크 정책을 관통하는 가장 중요한 세 가지 핵심 요소는 바로 '누가(Source)', '누구에게(Destination)', '무엇을 할지(Action)' 입니다.

이 세 가지만 기억하면 Cilium 정책의 절반은 이미 이해하신 겁니다!

  1. Source (누가 보내는가? 📤)
    • 트래픽을 시작하는 주체를 의미합니다. "A가 B에게 데이터를 보낸다"에서 'A'에 해당하죠.
    • Cilium에서는 특정 레이블(label)을 가진 파드 그룹(app=frontend 같은), 특정 IP 대역(CIDR), 또는 다른 엔티티로 소스를 명확하게 지정할 수 있습니다.
  2. Destination (누구에게 보내는가? 📥)
    • 트래픽을 수신하는 대상을 의미합니다. 위 예시에서 'B'에 해당하겠죠?
    • 일반적으로 정책이 적용되는 엔드포인트(파드) 자체를 의미하며, 더 나아가 특정 포트(port) 번호까지 지정하여 "80번 포트로 들어오는 트래픽만!"과 같이 세밀하게 제어할 수 있습니다.
  3. Action (어떻게 할 것인가? ✅)
    • 소스에서 데스티네이션으로 향하는 트래픽이 규칙과 일치했을 때, 어떤 조치를 취할지를 결정합니다.
    • Cilium의 가장 중요한 철학은 'Default Deny(기본적으로 모두 거부)' 입니다. 즉, 아무런 정책이 없으면 모든 파드 간의 통신은 차단됩니다. 따라서 우리가 만드는 정책은 특정 트래픽을 '허용(Allow)' 하는 '화이트리스트' 방식이 됩니다. 이 '허용'이 바로 Action에 해당합니다.

🗺️ 전체 그림으로 이해하기: Default Deny와 허용 정책

개별 요소를 아는 것도 중요하지만, 전체적인 흐름을 이해하면 Cilium의 강력함을 제대로 느낄 수 있습니다.

상황을 가정해볼까요? 여러분의 클러스터에는 frontend 파드와 backend 파드가 있습니다. frontend는 사용자의 요청을 받아 backend에 API 요청을 보내야 합니다.

  1. 정책 적용 전 (Default Deny) 🚫
    • Cilium이 적용된 환경에서는 기본적으로 frontend와 backend는 서로 통신할 수 없습니다. 모든 길이 막혀있는 상태라고 생각하시면 됩니다. frontend가 backend를 호출해도 응답이 오지 않습니다.
  2. 정책 적용 후 (Allow Rule) ✅
    • 우리는 이제 frontend가 backend의 8080 포트로 통신하는 것을 '허용'하는 정책을 만들어야 합니다.
    • Source: app=frontend 레이블을 가진 파드
    • Destination: app=backend 레이블을 가진 파드, 포트는 8080
    • Action: 이 통신을 허용(Allow)한다.

이 정책을 적용하는 순간, 막혀있던 두 파드 사이에 안전한 통신 채널이 열리게 됩니다. ✨


💻 코드로 직접 확인하기: Frontend가 Backend를 호출하도록 허용하기

백문이 불여일견! 실제 CiliumNetworkPolicy YAML 파일을 통해 위 시나리오를 어떻게 구현하는지 살펴보겠습니다. 이 정책은 backend 파드에 적용되어, frontend로부터 오는 트래픽을 허용하는 규칙입니다.

# CiliumNetworkPolicy 정의 (API 버전과 종류)
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  # 정책이 적용될 네임스페이스
  namespace: my-app
  # 정책의 이름
  name: backend-allow-from-frontend
spec:
  # --- Destination ---
  # 이 정책이 어떤 파드에 적용될지를 선택합니다.
  # 'app=backend' 레이블을 가진 모든 파드가 대상입니다.
  endpointSelector:
    matchLabels:
      app: backend

  # --- Action (Allow) + Source/Destination Port ---
  # 'ingress'는 들어오는 트래픽에 대한 규칙을 의미합니다.
  ingress:
  - fromEndpoints:
      # --- Source ---
      # 'app=frontend' 레이블을 가진 파드로부터의 트래픽을 허용합니다.
      - matchLabels:
          app: frontend
    toPorts:
      # --- Destination Port ---
      # 8080/TCP 포트로 들어오는 트래픽에만 이 규칙을 적용합니다.
      - ports:
        - port: "8080"
          protocol: TCP

YAML 파일 해석:

  • endpointSelector: 이 정책의 Destination(대상)이 누구인지 정의합니다 (app=backend 파드).
  • ingress: 들어오는 트래픽에 대한 규칙임을 명시합니다.
  • fromEndpoints: 트래픽의 Source(출발지)가 누구인지 정의합니다 (app=frontend 파드).
  • toPorts: Destination의 특정 포트를 명시하여 규칙을 더 세밀하게 만듭니다.
  • 이 YAML 파일 자체를 클러스터에 적용하는 행위가 바로 Action(허용)을 의미합니다.

🧐 잠깐, 이건 왜 정답이 아닐까요?

비슷해 보이지만 핵심에서 벗어난 개념들도 있습니다. 왜 이것들이 기본 구조가 아닌지 이해하면 개념이 더 명확해집니다.

  • ❌ Pod, Service, Namespace
    • 이유: 이들은 쿠버네티스의 '오브젝트' 또는 '리소스'입니다. Cilium 정책은 이 오브젝트들을 활용하여 Source나 Destination을 '지정' 하지만, 정책 규칙 자체의 근본적인 구조(누가, 누구에게, 어떻게)는 아닙니다. 즉, 재료일 뿐, 레시피의 기본 단계는 아닌 셈이죠.
  • ❌ Ingress, Egress, Protocol
    • 이유: Ingress(수신)와 Egress(송신)는 트래픽의 '방향'을 나타냅니다. Protocol(TCP/UDP)은 통신 '규약'이죠. 이것들은 정책을 구성하는 매우 중요한 '속성'이지만, 'Source → Destination'이라는 흐름을 정의하는 더 큰 틀의 구성 요소는 아닙니다. 방향과 속성은 '누가 누구에게'라는 관계가 정해진 후에 구체화되는 세부 사항입니다.

마치며

이제 Cilium 네트워크 정책의 핵심이 보이시나요? 복잡해 보이는 YAML 파일도 결국은 "어떤 소스(Source)가, 어떤 목적지(Destination)로, 통신하는 것을 허용(Action)할 것인가?" 라는 간단한 질문에 답하는 과정일 뿐입니다.

이 세 가지 핵심 원칙만 잘 기억하신다면, 여러분의 쿠버네티스 클러스터를 그 어떤 위협으로부터도 안전하게 지켜내는 훌륭한 보안 아키텍트가 되실 수 있을 겁니다. 🚀