GKE Dataplane V2 사용


이 페이지에서는 Google Kubernetes Engine(GKE) 클러스터에 GKE Dataplane V2를 사용 설정하고 문제를 해결하는 방법을 설명합니다.

새 Autopilot 클러스터에는 1.22.7-gke.1500 이상 버전과 1.23.4-gke.1500 이상 버전의 GKE Dataplane V2가 사용 설정되어 있습니다. GKE Dataplane V2를 사용하는 데 문제가 있는 경우 문제 해결로 건너뛰세요.

GKE Dataplane V2로 GKE 클러스터 만들기

GKE 버전 1.20.6-gke.700 이상으로 새 클러스터를 만들 때 gcloud CLI나 Kubernetes Engine API를 사용하여 GKE Dataplane V2를 사용 설정할 수 있습니다. GKE 버전 1.17.9 이상을 사용하는 새 클러스터를 만들 때 미리보기에서 GKE Dataplane V2를 사용 설정할 수도 있습니다.

콘솔

GKE Dataplane V2로 새 클러스터를 만들려면 다음 작업을 수행하세요.

  1. Google Cloud 콘솔에서 Google Kubernetes Engine 페이지로 이동합니다.

    Google Kubernetes Engine으로 이동

  2. 만들기를 클릭합니다.

  3. 구성을 클릭하여 표준 클러스터를 구성합니다.

  4. 네트워킹 섹션에서 Dataplane V2 사용 설정 체크박스를 선택합니다. 네트워크 정책 적용이 GKE Dataplane V2에 내장되어 있으므로 Dataplane V2 사용 설정을 선택하면 Kubernetes 네트워크 정책 사용 설정 옵션이 사용 중지됩니다.

  5. 만들기를 클릭합니다.

gcloud

GKE Dataplane V2를 사용하여 새 클러스터를 만들려면 다음 명령어를 사용하세요.

gcloud container clusters create CLUSTER_NAME \
    --enable-dataplane-v2 \
    --enable-ip-alias \
    --release-channel CHANNEL_NAME \
    --location COMPUTE_LOCATION

다음을 바꿉니다.

  • CLUSTER_NAME: 새 클러스터의 이름입니다.
  • CHANNEL_NAME: GKE 버전 1.20.6-gke.700 이상을 포함하는 출시 채널입니다. 출시 채널을 사용하지 않으려면 버전 1.20.6-gke.700 이상을 지정하여 --release-channel 대신 --cluster-version 플래그를 사용할 수도 있습니다.
  • COMPUTE_LOCATION: 새 클러스터의 Compute Engine 위치입니다.

API

GKE Dataplane V2로 새 클러스터를 만들려면 클러스터 create 요청networkConfig 객체에서 datapathProvider 필드를 지정합니다.

다음 JSON 스니펫은 GKE Dataplane V2를 사용 설정하는 데 필요한 구성을 보여줍니다.

"cluster":{
   "initialClusterVersion":"VERSION",
   "ipAllocationPolicy":{
      "useIpAliases":true
   },
   "networkConfig":{
      "datapathProvider":"ADVANCED_DATAPATH"
   },
   "releaseChannel":{
      "channel":"CHANNEL_NAME"
   }
}

다음을 바꿉니다.

  • VERSION: 클러스터 버전이며 GKE 1.20.6-gke.700 이상이어야 합니다.
  • CHANNEL_NAME: GKE 버전 1.20.6-gke.700 이상을 포함하는 출시 채널입니다.

GKE Dataplane V2 문제 해결

이 섹션에서는 GKE Dataplane V2의 문제를 조사하고 해결하는 방법을 설명합니다.

  1. GKE Dataplane V2가 사용 설정되었는지 확인합니다.

    kubectl -n kube-system get pods -l k8s-app=cilium -o wide
    

    GKE Dataplane V2가 실행 중이면 출력은 프리픽스가 anetd-인 포드를 포함합니다. anetd는 GKE Dataplane V2의 네트워킹 컨트롤러입니다.

  2. 서비스 또는 네트워크 정책 적용과 관련된 문제라면 anetd 포드 로그를 확인합니다. Cloud Logging에서 다음 로그 선택기를 사용합니다.

    resource.type="k8s_container"
    labels."k8s-pod/k8s-app"="cilium"
    resource.labels.cluster_name="CLUSTER_NAME"
    
  3. 포드 만들기가 실패하면 kubelet 로그에서 단서를 찾아보세요. Cloud Logging에서 다음 로그 선택기를 사용합니다.

    resource.type="k8s_node"
    log_name=~".*/logs/kubelet"
    resource.labels.cluster_name="CLUSTER_NAME"
    

    CLUSTER_NAME을 클러스터 이름으로 바꾸거나 완전히 삭제하여 모든 클러스터의 로그를 확인합니다.

알려진 문제

GKE Dataplane V2 클러스터의 NodePort 범위 충돌과 관련된 간헐적인 연결 문제

GKE Dataplane V2 클러스터에서 매스커레이드 트래픽 또는 임시 포트 사용에 간헐적인 연결 문제가 발생할 수 있습니다. 이러한 문제는 예약된 NodePort 범위와의 잠재적인 포트 충돌로 인해 발생하며 일반적으로 다음 시나리오에서 발생합니다.

  • 커스텀 ip-masq-agent: 클러스터에 NodePort 또는 부하 분산기 서비스가 있는 커스텀 ip-masq-agent(버전 2.10 이상)를 사용하는 경우 NodePort 범위와의 충돌로 인한 연결 문제가 간헐적으로 발생할 수 있습니다. 버전 2.10 이상부터 ip-masq-agent에는 기본적으로 내부적으로 구현된 --random-fully 인수가 있습니다. 이 문제를 완화하려면 ip-masq-agent 구성의 인수 아래에 --random-fully=false(버전 2.11부터 적용됨)를 명시적으로 설정하세요. 구성에 관한 자세한 내용은 Standard 클러스터에서 IP 매스커레이드 에이전트 구성을 참조하세요.

  • 임시 포트 범위 중복: GKE 노드의 net.ipv4.ip_local_port_range에 의해 정의된 임시 포트 범위가 NodePort 범위(30000~32767)와 겹치면 연결 문제를 트리거할 수도 있습니다. 이 문제를 방지하려면 이 두 범위가 겹치지 않도록 해야 합니다.

ip-masq-agent 구성 및 임시 포트 범위 설정이 NodePort 범위와 충돌하지 않는지 검토합니다. 간헐적인 연결 문제가 발생하면 이러한 잠재적인 원인을 고려하고 그에 따라 구성을 조정하세요.

네트워크 정책 포트 범위는 적용되지 않음

GKE Dataplane V2가 사용 설정된 클러스터의 네트워크 정책에 endPort 필드를 지정하면 적용되지 않습니다.

GKE 1.22부터 Kubernetes 네트워크 정책 API를 사용하면 네트워크 정책이 적용되는 포트 범위를 지정할 수 있습니다. 이 API는 Calico 네트워크 정책이 있는 클러스터에서 지원되지만 GKE Dataplane V2가 있는 클러스터에서는 지원되지 않습니다.

NetworkPolicy 객체를 API 서버에 작성한 후 다시 읽어 해당 객체의 동작을 확인할 수 있습니다. 객체에 여전히 endPort 필드가 포함되어 있으면 기능이 적용됩니다. endPort 필드가 누락되면 이 기능이 적용되지 않습니다. 어떤 경우든 API 서버에 저장된 객체는 네트워크 정책의 정보 소스입니다.

자세한 내용은 KEP-2079: 포트 범위를 지원하는 네트워크 정책을 참조하세요.

포드에 failed to allocate for range 0: no IP addresses available in range set 오류 메시지 표시

영향을 받는 GKE 버전: 1.22 ~ 1.25

containerd를 사용하고 GKE Dataplane V2가 사용 설정된 노드 풀을 실행하는 GKE 클러스터는 IP 주소 누출 문제가 발생할 수 있고 한 노드에서 포드 IP 주소를 모두 소진할 수 있습니다. 영향을 받는 노드에서 예약된 포드는 다음과 비슷한 오류 메시지를 표시합니다.

failed to allocate for range 0: no IP addresses available in range set: 10.48.131.1-10.48.131.62

이 문제에 대한 자세한 내용은 containerd 문제 #5768을 참조하세요.

수정된 버전

이 문제를 해결하려면 다음 GKE 버전 중 하나로 클러스터를 업그레이드합니다.

  • 1.22.17-gke.3100 이상
  • 1.23.16-gke.200 이상
  • 1.24.9-gke.3200 이상
  • 1.25.6-gke.200 이상

표준 GKE 클러스터의 해결 방법

노드의 누출된 포드 IP 주소를 삭제하여 이 문제를 완화할 수 있습니다.

누출된 포드 IP 주소를 삭제하려면 클러스터에 대해 인증 사용자 인증 정보를 가져오고 다음 단계를 실행하여 단일 노드를 삭제합니다(이름을 알고 있는 경우).

  1. 다음 셸 스크립트를 cleanup.sh 파일에 저장합니다.

    for hash in $(sudo find /var/lib/cni/networks/gke-pod-network -iregex '/var/lib/cni/networks/gke-pod-network/[0-9].*' -exec head -n1 {} \;); do hash="${hash%%[[:space:]]}"; if [ -z $(sudo ctr -n k8s.io c ls | grep $hash | awk '{print $1}') ]; then sudo grep -ilr $hash /var/lib/cni/networks/gke-pod-network; fi; done | sudo xargs -r rm
    
  2. 클러스터 노드에서 스크립트를 실행합니다.

    gcloud compute ssh --zone "ZONE" --project "PROJECT" NODE_NAME --command "$(cat cleanup.sh)"
    

    NODE_NAME을 허브 이름으로 바꿉니다.

이 스크립트의 DaemonSet 버전을 실행하여 모든 노드에서 한 번에 동시에 실행할 수도 있습니다.

  1. 다음 매니페스트를 cleanup-ips.yaml이라는 파일에 저장합니다.

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: cleanup-ipam-dir
      namespace: kube-system
    spec:
      selector:
        matchLabels:
          name: cleanup-ipam
      template:
        metadata:
          labels:
            name: cleanup-ipam
        spec:
          hostNetwork: true
          securityContext:
            runAsUser: 0
            runAsGroup: 0
          containers:
          - name: cleanup-ipam
            image: gcr.io/gke-networking-test-images/ubuntu-test:2022
            command:
              - /bin/bash
              - -c
              - |
                while true; do
                for hash in $(find /hostipam -iregex '/hostipam/[0-9].*' -mmin +10 -exec head -n1 {} \; ); do
                hash="${hash%%[[:space:]]}"
                if [ -z $(ctr -n k8s.io c ls | grep $hash | awk '{print $1}') ]; then
                grep -ilr $hash /hostipam
                fi
                done | xargs -r rm
                echo "Done cleaning up /var/lib/cni/networks/gke-pod-network at $(date)"
                sleep 120s
                done
            volumeMounts:
            - name: host-ipam
              mountPath: /hostipam
            - name: host-ctr
              mountPath: /run/containerd
          volumes:
          - name: host-ipam
            hostPath:
              path: /var/lib/cni/networks/gke-pod-network
          - name: host-ctr
            hostPath:
              path: /run/containerd
    
  2. 클러스터에서 daemonset을 실행합니다.

    kubectl apply -f cleanup-ips.yaml
    

    이 명령어를 실행하려면 클러스터의 관리자로서 kubectl 액세스 권한이 있어야 합니다.

  3. 실행 중인 DaemonSet의 로그를 확인합니다.

    kubectl -n kube-system logs -l name=cleanup-ipam
    

잘못된 연결 추적 조회로 인해 네트워크 정책이 연결을 중단

클라이언트 포드가 내부 패스 스루 네트워크 부하 분산기의 서비스나 가상 IP 주소를 통해 자체에 연결되면 응답 패킷은 데이터 영역의 잘못된 conntrack 조회로 인해 기존 연결의 일부로 식별되지 않습니다. 즉, 포드의 인그레스 트래픽을 제한하는 네트워크 정책이 패킷에 잘못 적용됩니다.

이 문제의 영향은 서비스에 구성된 포드 수에 따라 다릅니다. 예를 들어 서비스에 백엔드 포드가 1개 있으면 연결이 항상 실패합니다. 서비스에 백엔드 포드가 2개 있는 경우 연결의 50%가 실패합니다.

수정된 버전

이 문제를 해결하려면 다음 GKE 버전 중 하나로 클러스터를 업그레이드합니다.

  • 1.28.3-gke.1090000 이상

해결 방법

서비스 매니페스트에서 portcontainerPort를 동일한 값으로 구성하여 이 문제를 완화할 수 있습니다.

헤어핀 연결 흐름을 위한 패킷 삭제

포드가 서비스를 사용하여 자체 TCP 연결을 만들면(예: 포드가 연결의 소스이자 대상인 경우), GKE Dataplane V2 eBPF 연결 추적은 연결 상태를 잘못 추적하여 conntrack 항목의 유출로 이어지게 됩니다.

연결 튜플(프로토콜, 소스/대상 IP, 소스/대상 포트)이 유출되면 동일한 연결 튜플을 사용하는 새 연결로 인해 반환 패킷이 삭제될 수 있습니다.

수정된 버전

이 문제를 해결하려면 다음 GKE 버전 중 하나로 클러스터를 업그레이드합니다.

  • 1.28.3-gke.1090000 이상
  • 1.27.11-gke.1097000 이상

해결 방법

이때 다음 해결방법 중 하나를 사용해 보세요.

  • 서비스를 사용하여 자체적으로 통신할 수 있는 포드에서 실행되는 애플리케이션에 TCP 재사용(연결 유지)을 사용 설정합니다. 이렇게 하면 TCP FIN 플래그가 발급되지 않고 conntrack 항목의 유출이 방지됩니다.

  • 단기 연결을 사용할 때는 게이트웨이와 같은 프록시 부하 분산기를 사용하여 포드를 노출하여 서비스를 노출하세요. 그러면 연결 요청의 대상이 부하 분산기 IP 주소로 설정되고, GKE Dataplane V2가 루프백 IP 주소로 SNAT를 수행하지 못하게 됩니다.

다음 단계