클러스터 네트워크 정책 구성

ClusterNetworkPolicy를 사용하면 전체 클러스터에서 전역 GKE 보안 상황을 정의할 수 있습니다. 이 문서는 필수 보안 가이드레일을 적용하거나 제로 트러스트 기준을 설정해야 하는 클러스터 관리자를 대상으로 합니다.

이 리소스는 표준 네임스페이스 범위 NetworkPolicy 리소스보다 우선순위가 높은 엄격한 평가 계층 구조를 사용합니다. ClusterNetworkPolicy 리소스를 사용하여 명시적 거부, 수락 또는 통과 작업을 구현할 수 있습니다. 이러한 작업을 통해 전역 허용 또는 거부 정책을 구성하고, 특정 네임스페이스에 트래픽 제어를 위임하고, CIDR 블록으로의 이그레스 트래픽을 제한할 수 있습니다.

시작하기 전에

클러스터 네트워크 정책을 구성하기 전에 다음 요구사항을 충족하는지 확인하세요.

  1. GKE 클러스터가 버전 1.36.0-gke.4447000 이상을 실행하는지 확인합니다.
  2. 클러스터가 GKE Dataplane V2를 사용하는지 확인합니다.

지원되는 프로토콜 및 포트

ClusterNetworkPolicy 규칙은 TCP, UDP 또는 SCTP 프로토콜을 기반으로 트래픽을 일치시킬 수 있습니다. 다음과 같은 방법으로 대상 포트를 지정할 수 있습니다.

  • 특정 포트 번호: destinationPort.number 설정을 사용하여 단일 포트 (예: 80)를 타겟팅합니다.
  • 포트 범위: destinationPort.range 설정을 사용하여 포트 범위를 타겟팅합니다 (예: 8000~9000).
  • 이름이 지정된 포트: destinationNamedPort 설정을 사용하여 포드 사양에 정의된 기호 이름을 타겟팅합니다.

정책 평가 계층 구조

표준 추가 NetworkPolicy와 달리 ClusterNetworkPolicy (CNP)는 첫 번째 일치 규칙이 우선하는 엄격한 평가 계층 구조를 사용합니다. 트래픽은 다음 세 가지 레이어 파이프라인을 통해 순차적으로 흐릅니다.

  • 등급: 관리자 규칙이 먼저 실행되고 NetworkPolicy, 기준 순으로 캐스케이드됩니다.
  • CNP 우선순위: 계층 내에서 정책은 명시적 숫자 우선순위에 따라 평가됩니다.
  • CNP 규칙 순서: 단일 정책 내에서 규칙은 액세스 제어 목록 (ACL)과 같이 위에서 아래로 처리됩니다.

GKE 네트워크 정책 평가 계층 구조를 보여주는 다이어그램

위 다이어그램은 CNP 평가 계층 구조의 결정 흐름을 보여줍니다.

  1. 관리자 등급: 트래픽은 먼저 Admin 등급의 ClusterNetworkPolicy 규칙에 대해 평가됩니다. 허용 또는 거부 일치가 있으면 평가가 중지됩니다. 일치하는 항목이 없거나 Pass 작업이 있으면 트래픽이 NetworkPolicy 등급으로 진행됩니다.
  2. NetworkPolicy 등급: 트래픽이 표준 네임스페이스 정책에 따라 평가됩니다. 일치하는 항목이 있으면 트래픽이 허용됩니다. 일치하는 항목이 없으면 트래픽은 기준 등급으로 진행됩니다.
  3. 기준 등급: 트래픽이 기준 등급의 ClusterNetworkPolicy 규칙에 따라 평가됩니다. 허용 또는 거부 일치가 있으면 평가가 중지됩니다. 일치하는 항목이 없으면 트래픽은 기본 동작으로 진행됩니다.
  4. 기본 GKE 동작: 어떤 계층에서도 일치하는 정책이 없으면 트래픽에 암시적 허용 동작이 적용됩니다.

판결 작업: 허용, 거부, 통과

패킷이 일치하면 모든 규칙이 다음 세 가지 엄격한 작업 중 하나를 트리거합니다.

  • 거부: 트래픽을 즉시 차단합니다.
  • 수락: 트래픽을 허용합니다. 두 작업 모두 파이프라인을 즉시 단락시켜 나머지 모든 정책을 무시합니다.
  • Pass: 제어를 다음 계층으로 전달하여 플랫폼 엔지니어가 전반적인 관리 제어를 포기하지 않고도 특정 트래픽 결정을 표준 네임스페이스 수준 정책에 위임할 수 있습니다.

전역 거부 정책 구성

민감한 네임스페이스를 다른 모든 클러스터 내부 트래픽에서 격리하려면 재정의할 수 없는 거부 규칙을 적용하세요. 이 기본 거부 정책은 민감한 네임스페이스로 오가는 트래픽이 관리 수준에서 차단되도록 하는 데 도움이 됩니다. 이 정책은 네임스페이스 수준 규칙에 의해 실수로 우회될 수 없는 보호 기준 역할을 합니다.

  1. 다음 매니페스트를 global-deny.yaml로 저장합니다.

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: cluster-wide-deny-sensitive
    spec:
      tier: Admin
      priority: 10
      subject:
        namespaces:
          matchLabels:
            kubernetes.io/metadata.name: sensitive-ns
      ingress:
      - action: Deny
        name: deny-all-ingress
        from:
        - namespaces:
            matchLabels: {}
      egress:
      - action: Deny
        name: deny-all-egress
        to:
        - namespaces:
            matchLabels: {}
    
  2. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f global-deny.yaml
    

전역 허용 정책 구성

전역 허용 정책을 사용하면 개발자가 만든 네트워크 정책과 관계없이 모든 포드가 클러스터 DNS 서비스에 도달할 수 있습니다.

  1. 다음 매니페스트를 global-allow-dns.yaml로 저장합니다.

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: allow-kube-dns-admin
    spec:
      tier: Admin
      priority: 20
      subject:
        namespaces: {}
      egress:
      - action: Accept
        name: allow-dns-egress
        to:
        - pods:
            namespaceSelector:
              matchLabels:
                kubernetes.io/metadata.name: kube-system
            podSelector:
              matchLabels:
                k8s-app: kube-dns
        protocols:
        - udp:
            destinationPort:
              number: 53
        - tcp:
            destinationPort:
              number: 53
    
  2. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f global-allow-dns.yaml
    

트래픽을 네임스페이스 정책에 위임

특정 트래픽 패턴을 표준 네임스페이스 범위 NetworkPolicy 객체에 위임합니다.

  1. 다음 매니페스트를 delegate-policy.yaml로 저장합니다.

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: delegate-to-netpol
    spec:
      tier: Admin
      priority: 30
      subject:
        namespaces: {}
      egress:
      - action: Pass
        name: delegate-web-traffic
        to:
        - namespaces:
            matchLabels:
              app: web-backend
        protocols:
        - tcp:
            destinationPort:
              number: 8080
    
  2. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f delegate-policy.yaml
    
  3. 타겟 네임스페이스 내에서 위임된 트래픽을 허용하려면 다음 표준 NetworkPolicy 매니페스트를 allow-web-backend.yaml로 저장합니다.

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-web-backend
      namespace: backend-ns
    spec:
      podSelector:
        matchLabels:
          app: web-backend
      ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              app: web-frontend
        ports:
        - protocol: TCP
          port: 8080
    
  4. 표준 NetworkPolicy 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f allow-web-backend.yaml
    

기준 가드레일 구성

네임스페이스 관리자가 표준 네트워크 정책을 사용하여 재정의할 수 있는 기본 GKE 보안 자세를 설정합니다.

  1. 다음 기준 매니페스트를 baseline-deny.yaml로 저장합니다.

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: default-deny-baseline
    spec:
      tier: Baseline
      priority: 100
      subject:
        namespaces: {}
      ingress:
      - action: Deny
        name: baseline-deny-all
        from:
        - namespaces: {}
    
  2. 기준 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f baseline-deny.yaml
    
  3. 다음 개발자 재정의 매니페스트를 developer-allow.yaml로 저장합니다.

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-frontend-access
      namespace: my-app-ns
    spec:
      podSelector:
        matchLabels:
          app: frontend
      ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: ingress-nginx
    
  4. 재정의 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f developer-allow.yaml
    

이름이 지정된 포트를 사용하여 정책 구성

보안 정책에서 포트 번호를 추상화하려면 포드 사양에 정의된 이름이 지정된 포트를 참조하세요.

  1. 다음 배포 매니페스트를 app-deployment.yaml로 저장합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-webapp
    spec:
      template:
        spec:
          containers:
          - name: web-container
            image: nginx
            ports:
            - name: http-web
              containerPort: 8080
    
  2. 배포 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f app-deployment.yaml
    
  3. 다음 정책 매니페스트를 named-port-policy.yaml로 저장합니다.

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: allow-web-named-port
    spec:
      tier: Admin
      priority: 40
      subject:
        namespaces: {}
      egress:
      - action: Accept
        to:
        - namespaces:
            matchLabels:
              app: my-webapp
        protocols:
        - tcp:
            destinationNamedPort: http-web
    
  4. 정책 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f named-port-policy.yaml
    

이그레스를 CIDR 블록으로 제한

CIDR 블록을 지정하여 외부 리소스 또는 회사 인트라넷에 대한 액세스를 제어합니다.

  1. 다음 매니페스트를 cidr-policy.yaml로 저장합니다.

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: allow-egress-to-intranet
    spec:
      tier: Admin
      priority: 60
      subject:
        namespaces: {}
      egress:
      - action: Accept
        name: allow-intranet
        to:
        - networks:
          - 10.0.0.0/8
          - 192.168.0.0/16
    
  2. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f cidr-policy.yaml
    

우선순위 우선순위 구성

동일한 포드에 여러 정책이 적용될 때 평가 순서를 제어하려면 우선순위를 지정하세요. 우선순위는 0~1000이며 숫자가 낮을수록 우선순위가 높습니다. 단일 ClusterNetworkPolicy 객체는 최대 100개의 인그레스 규칙과 100개의 이그레스 규칙을 포함할 수 있습니다.

  1. 다음 매니페스트를 priority-policies.yaml로 저장합니다.

    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: deny-beta
    spec:
      tier: Admin
      priority: 10
      subject:
        namespaces:
          matchLabels:
            team: alpha
      ingress:
      - action: Accept
        name: allow-beta-monitoring
        from:
        - pods:
            namespaceSelector:
              matchLabels:
                team: beta
            podSelector:
              matchLabels:
                app: monitoring
      - action: Deny
        name: deny-all-other-ingress-from-beta
        from:
        - namespaces:
            matchLabels:
              team: beta
    ---
    apiVersion: policy.networking.k8s.io/v1alpha2
    kind: ClusterNetworkPolicy
    metadata:
      name: allow-beta
    spec:
      tier: Admin
      priority: 50
      subject:
        namespaces:
          matchLabels:
            team: alpha
      ingress:
      - action: Accept
        name: allow-all-ingress-from-beta
        from:
        - namespaces:
            matchLabels:
              team: beta
    
  2. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f priority-policies.yaml
    

문제 해결

정책 오류를 진단하고 해결하는 방법을 알아보려면 다음 명령어를 사용하세요.

클러스터의 모든 클러스터 네트워크 정책을 나열합니다.

kubectl get clusternetworkpolicies

특정 정책을 설명하여 상태와 평가 등급을 검사합니다.

kubectl describe clusternetworkpolicy/<policy-name>

출력의 status.conditions 필드는 클러스터의 네트워킹 구현에 의해 정책이 성공적으로 조정되었는지에 관한 정보를 제공합니다.

트래픽 흐름과 정책 결정을 모니터링하려면 GKE Dataplane V2 관측 가능성을 사용하세요.

다음 단계