8. CNI 기반 네트워크 정책

MAYFIFTH·2025년 6월 6일

K8S

목록 보기
8/10

쿠버네티스가 기본적으로 제공하는 네트워크 정책 구성 요소들로만으로는 실무 환경에서 발생하는 다양한 네트워크 정책을 구현하기 쉽지 않다.

이를 보완해주는게 바로 CNI 플러그인이다.

  • CNI 자체적으로 확장된 네트워크 정책을 제공
  • 유료 기능이 많긴 하다.

쿠버네티스 네트워크 정책은 L3(IP), L4(Port) 계층의 트래픽만 제어 가능하고, L7 트래픽을 제어할 순 없다.

  • 이 또한 CNI를 사용하면 해결할 수 있다.

🎯 쿠버네티스 표준 NetworkPolicy

  1. 파드의 수신 및 송신 트래픽을 제어하여 트래픽을 제한하는 표준 쿠버네티스 리소스
  2. 파드 레벨, 네임스페이스, IP 범위를 지정하여 L3, L4 레이어의 트래픽 제어 가능
  3. 기본 정책이 없으면 모두 허용 상태로 동작하고, 정책 선언 시 허용된 정책만 통신 가능하도록 변경됨

📌 표준 NetworkPolicy의 한계

  1. FQDN(Fully Qualifed Domain Name) 기반 제어 지원 X
    🔹 IP 기반의 정책은 생성 가능하지만, 수시로 변하는 Pod의 IP 특성상 도메인 기반 접근 제어가 필수적이다.

  2. L7 레이어 제어 지원 X
    🔹 Pod 내 애플리케이션의 HTTP Path, method, KafkaL7 프로토콜 등의 세부적인 정책 미지원

  3. TLS 연관 정책 미지원
    🔹 암호화 통신에 대한 정책이 별도로 지원되지 않으므로, ServiceMeshIngres Controller 의 보조 필요

  4. 클러스터 단위 정책 등의 일괄적 정책 적용 미지원
    🔹 클러스터 내 모든 노드, 네임스페이스, 파드에 적용 후 유지할 수 있는 정책이 별도 존재 X

  5. 네트워크 정책이 적용된 대상들에 대한 로깅 기능 지원 X
    🔹 적용한 네트워크 정책과 매칭되는 로그를 출력되는 기능이나, 실시간 로깅을 통한 가시성 확보 등의 기능 지원 X

1️⃣ Calico

✅GlobalNetworkPolicy

🔹 Calico에서 제공하는 확장 네트워크 정책으로, 네임스페이스에 국한되지 않고 클러스터 전체에 적용할 수 있게 해준다.
🔹 명시적 차단 기능(action:Deny), DNS 기반 제어, 정책 우선 순위(tier, order) 등 다양한 확장 기능 지원
🔹 log: true 설정을 통한 정책과 매칭되는 로그를 수집할 수 있는 로깅 기능도 지원함

  • 예시

명시적 Deny

apiVersion: protectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: deny-ssh
spec:
  selector: all()
  ingress:
    - action: Deny # 명시적 차단!
    destination:
      ports: [22]
  types:
    - Ingress

특정 도메인 허용

apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: allow-egress-to-domains
spec:
  selector: all()
  types:
  - Egress
  egress:
    - action: Allow
    protocol: UDP
    destination:
      ports:
        - 53
    - action: Allow
    destination: # 특정 도메인 허용 기능!(유료 기능)
      domains:
        - api.example.com
        - '*.example.org'

🚨 DNS 기반 제어 기능은 Calico의 유료 버전만 지원한다

✅StagedNetworkPolicy

🔹 Calico에서 제공하는 정책 시뮬레이션 및 단계적 적용을 위한 확장 리소스
🔹 실수로 모든 트래픽을 차단하는 문제 방지, 정책 충돌 원인 파악에 유용
🔹 적용 전, 적용 후로 나누어 세밀한 트래픽 제어 가능

모든 Ingress 트래픽을 기록(Log)만 수행

# only logging ingress traffic without block
apiVersion: projectcalico.org/v3
kind: StagedNetworkPolicy
metadata:
  name: log-all-ingress
spec:
  selector: app == "web"
  ingress:
    preRules:
      - action: Log
        source:
          nets:
            - 0.0.0.0/0

모든 Ingress 트래픽을 기록하고, 그중 SSH(22번 포트)만 차단

# logging all ingress & only block 22 port
apiVersion: projectcalico.org/v3
kind: StagedNetworkPolicy
metadata:
  name: deny-ssh-after-log
spec:
  selector: all()
  ingress:
    preRules:
      - action: Log
    postRules:
      - action: Deny
        destination:
          ports: [22]

🧠StagedNetworkPolicy는 Calico의 "미리 시뮬레이션" 기능으로,
🔹 실제로 트래픽을 차단하지 않고, 어떤 정책이 어떤 트래픽에 적용될지 사전 테스트 가능
🔹 운영 중인 시스템에 영향을 최소화하며 정책을 실험할 수 있는 안전한 방법


2️⃣ Cilium

✅CiliumNetworkPolicy

🔹 Cilium에서 제공하는 확장 네트워크 리소스로, 다양한 L7 트래픽 세밀 제어 지원
🔹 Hubble UI를 통한 정책 적용 결과 확인 가능
     🔸 트래픽 추적 지원 등의 정책 적용 후 가시성 지원
🔹 IP, FQDN 외에도 파드의 Security Identity를 기반으로 하는 Identity 정책 적용 지원

allow-get-healthz.yaml

# only allow GET /healthz req
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-get-healthz
spec:
  endpointSelector:
    matchLabels:
      app: my-api
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: frontend
      toPorts:
        - ports:
            - port: "80"
              protocol: TCP
          rules:
            http:
              - method: GET
                path: "/healthz"

allow-egress-to-openai.yaml

# only allow specific domain (openai)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-egress-to-openai
spec:
  endpointSelector:
    matchLabels: {}
  egress:
    - toFQDNs:
        - matchName: "api.openai.com"
      toPorts:
        - ports:
            - port: "443"
              protocol: TCP

✅CiliumClusterWideNetworkPolicy

🔹 GlobalNetworkPolicy 같이 클러스터 전체 워크로드에 적용 목적으로 지원하는 리소스
🔹 CiliumNetworkPolicy의 전역 일괄 적용이 필요한 경우 CiliumCluster*wide*NetworkPolicy를 활용

allow-openai-egress.yaml

# only openai domain across the cluster
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: allow-openai-egress
spec:
  endpointSelector:
    matchLabels: {}
  egress:
    - toFQDNs:
        - matchName: "api.openai.com"
      toPorts:
        - ports:
            - port: "443"
              protocol: TCP

allow-get-status.yaml

# only allow /status req in all namespaces
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: allow-get-status
spec:
  endpointSelector:
    matchLabels:
      role: api
  ingress:
    - fromEndpoints:
        - matchLabels:
            role: client
      toPorts:
        - ports:
            - port: "80"
          rules:
            http:
              - method: GET
                path: "/status"

🛠️ 주요 CNI 네트워크 정책 비교

🟢 DNS 기반 정책 제어

🔹CalicoGlobalNetworkPolicyegress 규칙에서 destination.domains 필드를 사용해 지원 가능
🔹내부적으로는 DNS를 주기적으로 조회해 IP를 계산하는 DNS IP 캐싱 기반으로 동작
   🔸dnsPolicy가 적용된 kube-dns , CoreDNS를 통해 FQDN->IP 변환 후 해당 IP 에 대한 egress 규칙을 적용
🔹단, 해당 도메인으로 나가는 트래픽만 정책이 적용되며, DNS 쿼리 패턴 매칭 등의 고급 기능은 지원 X

# DNS policy example
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: allow-egress-to-domains
spec:
  selector: all()
  types:
    - Egress
  egress:
    - action: Allow
      protocol: UDP
      destination:
        ports:
          - 53
    - action: Allow
      destination:
        domains:
          - api.example.com
          - '*.example.org'

🔹CiliumCiliumNetworkPolicy에서 toFQDN 필드를 사용해 도메인 기반 제어 지원
🔹또한, toPortsrules.dns.matchPattern을 통해서도 패턴 매칭 기반의 도메인 기반 제어 지원
🔹Cilium은 eBPF 기반 DNS request 가로채기를 수행하며, 식별된 IP에 대해 커널 레벨에서 제어 수행
   🔸eBPF DNS Tracker를 사용한 DNS 요청 및 응답 실시간 트래킹 수행 -> DNS 쿼리 필터링 등의 강력한 기능 지원
   🔸도메인과 매칭되는 IP가 변경될 경우, 자동으로 정책 동기화

# FQDN policy + DNS pattern matching
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "fqdn"
spec:
  endpointSelector:
    matchLabels:
      org: empire
      class: mediabot
  egress:
    - toFQDNs:
        - matchPattern: "*.github.com"
      toPorts:
        - ports:
            - port: "443"
              protocol: TCP
    - toEndpoints:
        - matchLabels:
            "k8s:io.kubernetes.pod.namespace": kube-system
            "k8s:k8s-app": kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: ANY
          rules:
            dns:
              - matchPattern: "*"

🟢 L7 애플리케이션 제어

🔹 Calico는 기본적으로 HTTP 메소드, URL 경로 등의 세부적인 트래픽 정책을 지원하지 않음
   🔸L7 필터링 지원을 위해서는 서비스 메시와의 연동, 혹은 애플리케이션 레벨 필터링 리소스 연동 필요
🔹 ApplicationLayer과 같은 custom resource를 통해 제한된 기능을 GlobalNetworkPolicy에 적용 가능
   🔸Ingress 규칙, 클러스터 레벨에만 적용 가능한 제한 사항이 존재함
   🔸 프로토콜 또한 HTTP, HTTPS, gRPC 등의 한정된 프로토콜만 지원

# ApplicationLayer Custom Resource
apiVersion: operator.tigera.io/v1
kind: ApplicationLayer
metadata:
  name: tigera-secure
spec:
  applicationLayerPolicy: Enabled
---
# Application Layer policy example
apiVersion: projectcalico.org/v3
kind: GlobalNetworkPolicy
metadata:
  name: customer
spec:
  selector: app == 'tradingapp'
  ingress:
    - action: Allow
      http:
        methods: ["GET"]
        paths:
          - exact: "/projects/calico"
          - prefix: "/users"
  egress:
    - action: Allow

🔹Cilium은 포트 기반 toPorts 규칙 아래 L7 필터링 정책을 정의하여 제어 가능
   🔸 rules.http.method, rules.http.path 필드를 통해 HTTP 메소드, 경로에 대한 요청 차단 및 허용 가능
🔹또한, Kafka topic이나 gRPC method 등의 프로토콜에 대한 topic 및 method 필터링 지원이 가능함
   🔸rules.kafka, rules.grpc 등의 필드를 통해 지원
🔹Cilium 내 내장된 eBPF + Envoy Proxy를 통해, 커널에서 L3/L4 처리 및 사용자 공간에서 L7 프록시 처리

# CiliumNetworkPolicy L7 policy
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-healthz
spec:
  endpointSelector:
    matchLabels:
      app: backend
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: frontend
      toPorts:
        - ports:
            - port: "80"
              protocol: TCP
          rules:
            http:
              - method: GET
                path: "/healthz"
profile
HARVEY

0개의 댓글