네트워크 정책 로깅 사용


이 페이지에서는 Google Kubernetes Engine(GKE)에 네트워크 정책 로깅을 사용하는 방법을 설명합니다. Kubernetes 네트워크 정책은 포드가 전송 및 수신할 수 있는 네트워크 트래픽을 지정합니다. 네트워크 정책 로깅을 사용하면 네트워크 정책에 따라 연결이 허용되거나 거부되는 시점을 기록할 수 있습니다. 네트워크 정책 로깅은 네트워크 정책 관련 문제를 해결하는 데 도움을 줄 수 있습니다.

개요

네트워크 정책 로깅을 사용하여 다음을 수행할 수 있습니다.

  • 네트워크 정책이 예상대로 작동하는지 확인합니다.
  • 클러스터의 어느 pod가 인터넷과 통신하는지 이해합니다.
  • 어느 네임스페이스가 서로 통신하는지 이해합니다.
  • 서비스 거부 공격을 인식합니다.

Cloud Logging이 사용 설정된 경우 네트워크 정책 로그는 저장, 검색, 분석, 알림을 위해 Cloud Logging에 업로드됩니다. Cloud Logging은 기본적으로 새 클러스터에서 사용 설정됩니다. 자세한 내용은 GKE의 로깅 및 모니터링 구성을 참조하세요.

요구사항

  • 네트워크 정책 로깅은 GKE Dataplane V2를 사용하는 클러스터에서만 사용할 수 있습니다.
  • 네트워크 정책 로깅을 사용하려면 Google Cloud CLI 303.0.0 이상이 필요합니다.
  • Windows Server 노드 풀에서는 네트워크 정책 로깅이 지원되지 않습니다.

가격 책정

  • 네트워크 정책 로깅에는 로그 생성 요금이 부과되지 않습니다.
  • Pub/Sub, Cloud Storage 또는 BigQuery로 로그를 라우팅할 수 있습니다. Pub/Sub, Cloud Storage 또는 BigQuery 요금이 적용될 수 있습니다. 자세한 내용은 라우팅 및 스토리지 개요를 참조하세요.

네트워크 정책 로깅 구성

클러스터에서 NetworkLogging 객체를 수정하여 네트워크 정책 로깅 설정을 구성합니다. GKE는 새 Dataplan V2 클러스터default라는 NetworkLogging 객체를 자동으로 만듭니다. 클러스터당 NetworkLogging 객체는 하나만 있을 수 있으며 이름은 변경할 수 없습니다.

허용된 연결의 로깅과 거부된 연결의 로깅을 별도로 구성할 수 있습니다. 일부 네트워크 정책에 대한 로깅을 선택적으로 사용 설정할 수도 있습니다. 다음은 모든 허용 및 거부된 연결을 로깅하도록 지정된 설정을 사용하는 NetworkLogging 사양의 예시입니다.

kind: NetworkLogging
apiVersion: networking.gke.io/v1alpha1
metadata:
  name: default
spec:
  cluster:
    allow:
      log: true
      delegate: false
    deny:
      log: true
      delegate: false

kubectl을 사용하여 구성을 수정하세요.

kubectl edit networklogging default

NetworkLogging 사양

NetworkLogging 객체 사양은 YAML 형식입니다. 이 형식에 대한 설명은 다음 표를 참조하세요.

필드유형설명
cluster.allowstruct 허용된 연결을 로깅하기 위한 설정
필드유형설명
log bool

true로 설정하면 클러스터의 허용 연결이 로깅됩니다. 그렇지 않으면 허용된 연결이 로깅되지 않습니다.

pod를 선택하고 연결과 일치하는 규칙이 있는 네트워크 정책은 로그 메시지에 나열됩니다.

delegate bool

false이면 허용된 모든 연결이 로깅됩니다. 여러 네트워크 정책이 연결을 허용하는 경우 일치하는 모든 정책이 로그 메시지에 나열됩니다.

true인 경우 허용된 연결이 로깅 주석 policy.network.gke.io/enable-logging: "true"가 있는 네트워크 정책에서 허용되는 경우에만 로깅됩니다. 여러 네트워크 정책이 연결을 허용하면 enable-logging 주석과 일치하는 모든 정책이 로그 메시지에 나열됩니다.

spec.cluster.allow.delegatetrue로, spec.cluster.allow.logfalse로 설정하면 구성 오류가 발생합니다.

cluster.deny struct 거부된 연결을 로깅하기 위한 설정
필드유형설명
log bool

true로 설정하면 클러스터의 거부된 연결이 로깅됩니다. 그러지 않으면 거부된 연결은 로깅되지 않습니다.

delegate bool

false인 경우 거부된 모든 연결이 로깅됩니다.

true이면 연결이 거부된 pod가 policy.network.gke.io/enable-deny-logging: "true" 주석이 있는 네임스페이스에 있는 경우에만 거부된 연결이 로깅됩니다.

spec.cluster.deny.delegatetrue로, spec.cluster.deny.logfalse로 설정하면 구성 오류가 발생합니다.

네트워크 정책 로그 액세스

네트워크 정책 로그는 Cloud Logging에 자동으로 업로드됩니다. 로그 탐색기 또는 Google Cloud CLI를 통해 로그에 액세스할 수 있습니다. 또한 싱크로 로그를 라우팅할 수도 있습니다.

Cloud Logging

  1. Google Cloud Console의 로그 탐색기 페이지로 이동합니다.

    로그 탐색기로 이동

  2. 쿼리 빌더를 클릭합니다.

  3. 다음 쿼리를 사용하여 모든 네트워크 정책 로그 기록을 찾습니다.

    resource.type="k8s_node"
    resource.labels.location="CLUSTER_LOCATION"
    resource.labels.cluster_name="CLUSTER_NAME"
    logName="projects/PROJECT_NAME/logs/policy-action"
    

    다음을 바꿉니다.

    • CLUSTER_LOCATION: 클러스터의 Compute Engine 위치입니다.
    • CLUSTER_NAME: 클러스터 이름입니다.
    • PROJECT_NAME: Google Cloud 프로젝트 이름입니다.

로그 탐색기 사용 방법을 알아보려면 로그 탐색기 사용을 참조하세요.

쿼리 빌더를 사용하여 쿼리를 작성할 수도 있습니다. 네트워크 정책 로그에 대한 쿼리를 만들려면 policy-action 드롭다운 목록에서 policy-action을 선택합니다. 사용 가능한 로그가 없으면 드롭다운 목록에 policy-action이 표시되지 않습니다.

gcloud

모든 네트워크 정책 로그 기록을 찾습니다.

gcloud logging read --project "PROJECT_NAME" 'resource.type="k8s_node"
    resource.labels.location="CLUSTER_LOCATION"
    resource.labels.cluster_name="CLUSTER_NAME"
    logName="projects/PROJECT_NAME/logs/policy-action"'

다음을 바꿉니다.

  • PROJECT_NAME: Google Cloud 프로젝트 이름입니다.
  • CLUSTER_LOCATION: 클러스터의 Compute Engine 위치입니다.
  • CLUSTER_NAME: 클러스터 이름입니다.

조건을 추가하여 결과를 필터링할 수 있습니다. 예를 들면 다음과 같습니다.

  • 특정 기간의 로그를 표시합니다.

    timestamp>="2020-06-22T06:30:51.128Z"
    timestamp<="2020-06-23T06:30:51.128Z"
    
  • 거부된 연결의 로그를 표시합니다.

    jsonPayload.disposition="deny"
    
  • 이름이 'redis'인 배포에 대한 로그를 표시합니다.

    jsonPayload.dest.pod_name=~"redis"
    jsonPayload.dest.pod_namespace="default"
    
  • 클러스터 외부 연결의 로그를 표시합니다.

    jsonPayload.dest.instance != ""
    
  • 특정 네트워크 정책과 일치하는 로그를 표시합니다(이 경우 'allow-frontend-to-db').

    jsonPayload.policies.name="allow-frontend-to-db"
    jsonPayload.policies.namespace="default"
    

표준 클러스터를 사용하는 경우 /var/log/network/policy_action.log*에 있는 각 클러스터 노드에서 로컬로 생성된 네트워크 정책 로그를 찾을 수도 있습니다. 현재 로그 파일이 10MB에 도달하면 새로운 번호가 지정된 로그 파일이 생성됩니다. 최대 5개의 이전 로그 파일이 저장됩니다.

네트워크 정책 로그 형식

네트워크 정책 로그 레코드는 JSON 형식입니다. 이 형식에 대한 설명은 다음 표를 참조하세요.

필드유형설명
connectionstruct 연결 정보
필드유형설명
src_ipstring연결의 소스 IP 주소입니다.
src_portint연결의 소스 포트입니다.
dest_ipstring연결의 대상 IP 주소입니다.
dest_portint연결의 대상 포트입니다.
protocolstring연결의 프로토콜(tcp, udp 또는 icmp 중 하나)입니다.
directionstring연결의 방향(ingress 또는 egress)입니다.
srcstruct 소스의 엔드포인트 정보입니다.
필드유형설명
pod_namestring소스가 pod인 경우 pod의 이름입니다.
pod_namespace (deprecated)string소스가 포드인 경우 포드의 네임스페이스입니다. pod_namespace가 지원 중단되었습니다. 대신 namespace를 사용하세요.
namespacestring소스가 포드인 경우 포드의 네임스페이스입니다.
workload_namestring소스 워크로드를 사용할 수 있는 경우 워크로드의 이름입니다.
workload_kindstring소스 워크로드를 사용할 수 있는 경우 워크로드의 종류입니다.
instancestring소스가 포드가 아닌 경우 소스의 IP 주소입니다.
deststruct 대상의 엔드포인트 정보입니다.
필드유형설명
pod_namestring대상이 pod인 경우 pod의 이름입니다.
pod_namespace (deprecated)string대상이 포드인 경우 포드의 네임스페이스입니다. pod_namespace가 지원 중단되었습니다. 대신 namespace를 사용하세요.
namespacestring대상이 포드인 경우 포드의 네임스페이스입니다.
workload_namestring대상 워크로드를 사용할 수 있으면 워크로드의 이름입니다.
workload_kindstring대상 워크로드를 사용할 수 있으면 워크로드의 종류입니다.
instancestring대상이 포드가 아닌 경우 소스의 IP 주소입니다.
dispositionstring연결의 배치(allow 또는 deny)입니다.
policieslist of structs

적용된 pod의 뷰에서 허용된 연결에 대한 일치하는 정책입니다. 인그레스 연결의 경우 적용된 pod는 대상 pod입니다. 이그레스 연결의 경우 적용된 pod는 소스 pod입니다. 연결이 이들 모두와 일치하는 경우 여러 정책이 로깅됩니다.

이 필드는 허용된 연결의 로그에만 포함됩니다.

필드유형설명
namestring일치하는 네트워크 정책의 이름입니다.
namespacestring일치하는 네트워크 정책의 네임스페이스입니다.
countint거부된 쿼리의 로그 집계에 사용됩니다. 허용되는 연결에 대해 값은 항상 1입니다.
node_namestring이 로그 메시지를 생성한 pod를 실행하는 노드입니다.
timestampstring연결 시도가 발생한 시간입니다.

연결의 정의

TCP와 같은 연결 지향적 프로토콜의 경우 허용되거나 거부된 연결마다 로그가 생성됩니다. 연결 지향적이지 않은 UDP 및 ICMP와 같은 프로토콜의 경우 패킷이 기간 기준 연결로 그룹화됩니다.

거부된 연결에 대한 정책 로그

Kubernetes 네트워크 정책 API에는 명시적인 거부 정책이 없으므로 거부된 연결의 로그 레코드에는 policies 필드가 포함되지 않습니다. 포드에 하나 이상의 네트워크 정책이 적용되는 경우 연결이 거부되지만 어떠한 정책도 연결을 허용하지 않습니다. 즉, 차단된 연결에 대해 개별적인 책임이 있는 정책이 없습니다.

거부된 연결의 로그 집계

클라이언트는 일반적으로 거부된 연결을 다시 시도합니다. 과도한 로깅을 방지하기 위해 5초 기간 내에 반복적으로 거부된 연결은 count 필드를 사용하여 단일 로그 메시지로 집계됩니다.

첫 번째로 거부된 연결과 연결의 src_ip, dest_ip, dest_port, protocol,, direction이 일치하는 경우 이후의 거부된 연결은 이전 로그 메시지로 집계됩니다. 재시도된 연결은 다른 포트에서 발생할 수 있으므로 후속 연결의 src_port는 일치하지 않아도 됩니다. 집계 로그 메시지에는 집계 창 시작 부분에 첫 번째로 거부된 연결의 src_prt가 포함됩니다.

로그 기록 예시

다음은 test-service에 적용된 allow-green이라는 네트워크 정책 예시에서는 client-green라는 pod에서 test-service에 연결하도록 허용합니다. 암시적으로 이 정책은 pod client-red를 포함하여 test-service에 대한 다른 모든 인그레스 트래픽을 거부합니다.

  apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: allow-green
    namespace: default
    annotations:
      policy.network.gke.io/enable-logging: "true"
  spec:
    podSelector:
      matchLabels:
        app: test-service
    ingress:
    - from:
      - podSelector:
          matchLabels:
            app: client-green
    policyTypes:
    - Ingress

이 다이어그램은 allow-green에 대한 두 개의 연결에서의 test-service 정책의 영향을 보여줍니다. allow-green 정책은 client-green에서의 연결을 허용합니다. client-red에서의 연결을 허용하는 정책이 없으므로 연결이 거부됩니다.

이미지

client-green에서 허용되는 연결의 로그는 다음과 같습니다.

{
   "connection":{
      "src_ip":"10.84.0.252",
      "dest_ip":"10.84.0.165",
      "src_port":52648,
      "dest_port":8080,
      "protocol":"tcp",
      "direction":"ingress"
   },
   "disposition":"allow",
   "policies":[
      {
         "name":"allow-green",
         "namespace":"default"
      }
   ],
   "src":{
      "pod_name":"client-green-7b78d7c957-68mv4",
      "pod_namespace":"default",
      "namespace":"default",
      "workload_name":"client-green-7b78d7c957",
      "workload_kind":"ReplicaSet"
   },
   "dest":{
      "pod_name":"test-service-745c798fc9-sfd9h",
      "pod_namespace":"default",
      "namespace":"default",
      "workload_name":"test-service-745c798fc9",
      "workload_kind":"ReplicaSet"
   },
   "count":1,
   "node_name":"gke-demo-default-pool-5dad52ed-k0h1",
   "timestamp":"2020-06-16T03:10:37.993712906Z"
}

client-red에서 거부된 연결의 로그는 다음과 같습니다.

{
   "connection":{
      "src_ip":"10.84.0.180",
      "dest_ip":"10.84.0.165",
      "src_port":39610,
      "dest_port":8080,
      "protocol":"tcp",
      "direction":"ingress"
   },
   "disposition":"deny",
   "src":{
      "pod_name":"client-red-5689846f5b-b5ccx",
      "pod_namespace":"default",
      "namespace":"default",
      "workload_name":"client-red-5689846f5b",
      "workload_kind":"ReplicaSet"
   },
   "dest":{
      "pod_name":"test-service-745c798fc9-sfd9h",
      "pod_namespace":"default",
      "namespace":"default",
      "workload_name":"test-service-745c798fc9",
      "workload_kind":"ReplicaSet"
   },
   "count":3,
   "node_name":"gke-demo-default-pool-5dad52ed-k0h1",
   "timestamp":"2020-06-15T22:38:32.189649531Z"
}

거부된 연결 로그에는 policies 필드가 포함되지 않습니다. 자세한 내용은 이전 섹션인 거부된 연결에 대한 정책 로그를 참조하세요.

거부된 연결 로그에는 거부된 연결 집계에 대한 count 필드가 포함됩니다.

네트워크 정책 로그 문제 해결

  1. NetworkLogging 객체에서 오류 이벤트를 확인합니다.

    kubectl describe networklogging default
    

    로깅 구성이 유효하지 않으면 구성이 적용되지 않으며 이벤트 섹션에 오류가 보고됩니다.

    Name:         default
    Namespace:
    Labels:       addonmanager.kubernetes.io/mode=EnsureExists
    Annotations:  API Version:  networking.gke.io/v1alpha1
    Kind:         NetworkLogging
    Metadata:
      Creation Timestamp:  2020-06-20T05:54:08Z
      Generation:          8
      Resource Version:    187864
      Self Link:           /apis/networking.gke.io/v1alpha1/networkloggings/default
      UID:                 0f1ddd6e-4193-4295-9172-baa6a52aa6e6
    Spec:
      Cluster:
        Allow:
          Delegate:  true
          Log:       false
        Deny:
          Delegate:  false
          Log:       false
    Events:
      Type     Reason                 Age                From                                                               Message
      ----     ------                 ----               ----                                                               -------
      Warning  InvalidNetworkLogging  16s (x3 over 11h)  network-logging-controller, gke-anthos-default-pool-cee49209-0t09  cluster allow log action is invalid: delegate cannot be true when log is false
      Warning  InvalidNetworkLogging  16s (x3 over 11h)  network-logging-controller, gke-anthos-default-pool-cee49209-80fx  cluster allow log action is invalid: delegate cannot be true when log is false
    
  2. 로깅에 사용되는 CPU 사용률을 제한하기 위해 노드는 로그를 삭제하기 전에 초당 최대 500개의 연결을 로깅할 수 있습니다. 노드의 네트워크 정책이 여전히 적용되고 있습니다. 오류 카운터가 증가하는지 확인하여 정책 로그가 삭제되었는지 확인할 수 있습니다.

    kubectl exec ANETD_POD_NAME -n kube-system -- curl -s http://localhost:9990/metrics |grep policy_logging
    

    ANETD_POD_NAME를 anetd 포드의 이름으로 바꿉니다. 각 노드를 확인합니다. anetd는 Dataplan V2의 네트워킹 컨트롤러입니다.

기본 거부 정책이 있는 포드에 이름이 없는 로그가 표시됩니다.

활성, 준비, 시작 프로브를 사용하려면 포드가 kubelet의 프로브에서 만들어진 인그레스 연결을 허용해야 합니다. 이러한 프로브가 올바르게 작동하도록 하기 위해 GKE는 포드에 적용되는 네트워크 정책에 관계없이 포드에 구성된 대로 선택된 포드에 대한 프로브 트래픽을 자동으로 허용합니다. 이 동작은 변경할 수 없습니다.

프로브 연결의 로그는 다음과 유사합니다.

{
   "connection":{
      "src_ip":"10.88.1.1",
      "dest_ip":"10.88.1.4",
      "src_port":35848,
      "dest_port":15021,
      "protocol":"tcp",
      "direction":"ingress"
   },
   "disposition":"allow",
   "src":{
      "instance":"10.88.1.1"
   },
   "dest":{
      "pod_name":"testpod-745c798fc9-sfd9h",
      "pod_namespace":"default",
      "namespace":"default",
      "workload_name":"testpod-745c798fc9",
      "workload_kind":"ReplicaSet"
   },
   "count":1,
   "policies": [
     {
       "name":""
     }
    ],
   "node_name":"gke-demo-default-pool-5dad52ed-k0h1",
   "timestamp":"2021-04-01T12:42:32.1898720941Z"
}

로그의 특성은 다음과 같습니다.

  • 연결을 허용하는 연결된 네트워크 정책이 없으므로 policies.name 값은 비어 있습니다.
  • connection.src_ip 값은 Pod 또는 노드에 해당하지 않습니다.

다음 단계