IPv4/IPv6 이중 스택 네트워킹

베어메탈용 Anthos 클러스터은 IPv4/IPv6 듀얼 스택 네트워킹을 지원합니다. 즉, 클러스터는 인터넷 프로토콜 버전 4(IPv4) 또는 인터넷 프로토콜 버전 6(IPv6)을 사용하는 외부 기기에서 들어오는 트래픽을 허용할 수 있습니다.

이중 스택 네트워킹은 포드 및 노드에 IPv4 주소와 IPv6 주소를 모두 할당합니다. Kubernetes 서비스에는 IPv4 주소, IPv6 주소 또는 둘 다 있을 수 있습니다.

모든 이중 스택 클러스터는 IPv6에 플랫 모드를 사용합니다. 기본적으로 이중 스택 클러스터는 IPv4에 섬(island) 모드를 사용하지만 IPv4에 플랫 모드를 사용하도록 구성할 수 있습니다.

이중 스택 클러스터를 만들려면 기본 네트워크에 이중 스택이 사용 설정되어 있어야 합니다. 기본 네트워크가 단일 스택 IPv4 또는 IPv6 네트워크인 경우 이중 스택 클러스터를 시작할 수 없습니다.

시작하기 전에

클러스터 노드가 CentOS 또는 RedHat Enterprise Linux를 실행 중이고 SELinux를 사용 설정한 경우 각 노드에서 다음을 수행합니다.

  • /etc/firewalld/firewalld.conf에서 IPv6_rpfilter=no를 설정합니다.

  • systemctl restart firewalld를 실행합니다.

이중 스택 클러스터 만들기 개요

새 클러스터를 만들 때 이중 스택 네트워킹을 사용 설정할 수 있지만 기존 클러스터에는 이중 스택 네트워킹을 사용 설정할 수 없습니다.

클러스터 만들기 문서 중 하나의 안내를 따르세요.

구성 파일에 다음 항목에 대한 매니페스트를 포함합니다.

  • 네임스페이스 리소스
  • 클러스터 리소스
  • 하나 이상의 NodePool 리소스
  • 하나 이상의 ClusterCIDRConfig 리소스

단일 스택 클러스터에서와 같이 네임스페이스 매니페스트와 NodePool 매니페스트를 입력합니다.

클러스터 매니페스트의 clusterNetwork.services.cidrBlocks에서 IPv4 CIDR 범위와 IPv6 CIDR 범위를 모두 지정합니다. 이는 이중 스택 클러스터의 사용 기준입니다. 즉, IPv4와 IPv6 모두에 서비스 CIDR 범위를 제공하는 경우 클러스터에 이중 스택 네트워크가 적용됩니다.

클러스터 매니페스트의 clusterNetwork.pods.cidrBlocks에서 IPv4 CIDR 범위를 지정하되 IPv6 CIDR 범위는 지정하지 않습니다. 포드의 IPv6 CIDR 범위는 ClusterCIDRConfig 매니페스트에 지정됩니다.

번들 부하 분산을 사용하는 경우 클러스터 매니페스트의 loadBalancer.addressPools 섹션에 IPv4 주소와 IPv6 주소를 모두 입력합니다.

ClusterCIDRConfig 리소스는 포드에 IPv4 및 IPv6 CIDR 범위를 지정하는 데 사용됩니다. 단일 ClusterCIDRConfig 리소스를 사용하여 클러스터 전체의 CIDR 범위를 지정할 수 있습니다. 즉, 모든 노드의 IPv4 포드 주소는 단일 CIDR 범위에서 가져오고 모든 노드의 IPv6 포드 주소는 단일 CIDR 범위에서 가져옵니다. 또는 여러 ClusterCIDRConfig 리소스를 사용하여 특정 노드 풀 또는 특정 노드에 적용되는 CIDR 범위를 지정할 수 있습니다.

포드 IP 주소의 연결 가능성

이중 스택 클러스터는 IPv6 네트워킹에 플랫 모드를 사용합니다. 이 문서에 제공된 예시는 IPv6에 정적 플랫 모드 네트워킹을 사용하는 클러스터를 위한 것입니다. 즉, 클러스터는 경계 게이트웨이 프로토콜(BGP)을 사용하도록 구성되지 않습니다.

정적 플랫 모드 네트워킹을 사용하는 클러스터의 경우 모두 동일한 서브넷의 일부인 노드 및 포드 IP 주소를 지정해야 합니다. 이렇게 하면 클러스터 외부에 있지만 클러스터 노드와 동일한 Layer 2(L2) 도메인에 있는 클라이언트가 패킷을 포드 IP 주소로 직접 보낼 수 있습니다.

예를 들어 클러스터 노드와 일부 기타 머신이 모두 동일한 L2 도메인에 있다고 가정해 보겠습니다. 주소 범위를 지정하는 방법은 다음과 같습니다.

목적범위주소 수
전체 L2 도메인fd12::/1082^20
포드fd12::1:0/1122^16
노드fd12::2:0/1122^16
기타 머신fd12::3:0/1122^16
VIPfd12::4:0/1122^16

앞의 예시에서 알아야 할 핵심 사항은 다음과 같습니다.

  • 모든 노드, 포드, 머신 주소는 큰 범위(fd12::/108)에 있습니다.

  • 포드 IP 주소는 큰 범위의 하위 집합에 있습니다.

  • 노드 IP 주소는 큰 범위의 다른 하위 집합에 있습니다.

  • 기타 머신의 IP 주소는 큰 범위의 다른 하위 집합에 있습니다.

  • 모든 하위 집합 범위는 서로 고유합니다.

앞의 예시에서 클러스터 노드를 포함하여 L2 도메인에 있는 각 머신에는 큰 범위에 대한 전달 규칙이 있어야 합니다. 예를 들면 다음과 같습니다.

inet fd12::/108 scope global eth0

예: 이중 스택 클러스터 만들기

이중 스택 클러스터를 만들 때 다양한 옵션을 사용할 수 있습니다. 예를 들어 클러스터 전체 CIDR 범위가 있거나 특정 노드 풀에 적용되는 CIDR 범위가 있을 수 있습니다. IPv6 평면 네트워크를 IPv4 섬(island) 모드 네트워크와 결합할 수 있습니다. 또는 IPv4 네트워크와 IPv6 네트워크 모두 평면일 수 있습니다. 번들 부하 분산 또는 수동 부하 분산을 사용할 수 있습니다.

이 섹션에서는 이중 스택 클러스터를 만드는 방법의 한 가지 예시를 제공합니다. 이 예시의 클러스터는 다음과 같은 특성을 갖습니다.

  • 섬(island) 모드의 IPv4 네트워크
  • 플랫 모드의 IPv6 네트워크
  • 포드의 클러스터 전체 IPv4 CIDR 범위
  • 포드의 클러스터 전체 IPv6 CIDR 범위
  • 서비스의 클러스터 전체 IPv4 CIDR 범위
  • 서비스의 클러스터 전체 IPv6 CIDR 범위
  • LoadBalancer 유형의 서비스에 사용될 IPv4 주소 풀
  • LoadBalancer 유형의 서비스에 사용될 IPv6 주소 풀
  • 번들 부하 분산

추가 구성 예시는 ClusterCIDRConfig 사용 변형을 참조하세요.

구성 파일 작성

클러스터 만들기 문서 중 하나의 안내를 따르세요.

구성 파일의 Cluster 매니페스트에서 다음을 수행합니다.

  • clusterNetwork.pods.cidrBlocks에 단일 IPv4 CIDR 범위를 제공합니다.

  • clusterNetwork.services.cidrBlocks에 2개의 CIDR 범위(IPv4와 IPv6에 하나씩)를 제공합니다.

  • loadBalancer.addressPools에 IPv4용과 IPv6용으로 각각 하나씩 2개의 주소 범위를 제공합니다. LoadBalancer 유형의 서비스를 만들면 서비스의 외부 IP 주소가 이 범위에서 선택됩니다.

다음은 클러스터 매니페스트의 관련 부분을 보여주는 예시입니다.

apiVersion: baremetal.cluster.gke.io/v1
kind: Cluster
metadata:
  name: "dual-stack"
  namespace: "cluster-dual-stack"

spec:
  clusterNetwork:
    pods:
      cidrBlocks:
      - "192.168.0.0/16"
    services
      cidrBlocks:
       - "172.16.0.0/20"
       - "fd12::5:0/116"
...
  loadBalancer:
    mode: "bundled"
    ...
    addressPools:
    - name: "pool-1"
      addresses:
       - "10.2.0.212-10.2.0.221"
       - "fd12::4:101-fd12::4:110"

동일한 구성 파일에 ClusterCIDRConfig의 매니페스트를 포함합니다.

  • ipv4.cidrCluster 매니페스트에서 제공한 CIDR 범위로 설정합니다. 이는 IPv4가 섬(island) 모드인 경우 요구사항입니다.

  • namespaceCluster 매니페스트에서 제공한 값과 동일하게 설정합니다.

  • ipv6.cidr을 포드의 IPv6 CIDR 범위로 설정합니다.

  • 각 CIDR 범위에 perNodeMaskSize 값을 제공하여 각 노드에 할당될 포드 주소 수를 지정합니다. 각 노드에 할당된 IPv4 주소의 수는 각 노드에 할당된 IPv6 주소의 수와 동일해야 합니다. perNodeMaskSize의 값을 이에 따라 설정해야 합니다. 예를 들어 노드당 2^8개의 주소를 원하는 경우 다음과 같이 perNodeMaskSize 값을 설정합니다.

    • ipv4.perNodeMaskSize: 24 # (32 - 8 = 24)
    • ipv6.perNodeMaskSize: 120 # (128 - 8 = 120)

다음은 ClusterCIDRConfig 매니페스트의 예시입니다.

apiVersion: baremetal.cluster.gke.io/v1alpha1
kind: ClusterCIDRConfig
metadata:
  name: "cluster-wide-ranges"
  namespace: "cluster-dual-stack"  # Must be the same as the Cluster namespace.
spec:
  ipv4:
    cidr: "192.168.0.0/16"  #  For island mode, must be the same as the Cluster CIDR.
    perNodeMaskSize: 24
  ipv6:
    cidr: "fd12::1:0/112"
    perNodeMaskSize: 120

앞의 예시를 다시 보겠습니다.

  • IPv4 포드 CIDR 범위에는 2^(32-16) = 2^16개의 주소가 있습니다. 노드당 마스크 크기는 24이므로 각 노드에 할당된 주소 수는 2^(32-24) = 2^8입니다.

  • IPv6 포드 CIDR 범위에는 2^(128-112) = 2^16개의 주소가 있습니다. 노드당 마스크 크기는 120이므로 각 노드에 할당된 주소 수는 2^(128-120) = 2^8개입니다.

구성 파일 예시

클러스터 만들기 완료

클러스터 만들기 문서에 설명된 대로 클러스터 만들기를 마칩니다.

클러스터 노드 및 포드 보기

클러스터 노드를 나열합니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG get nodes --output yaml

CLUSTER_KUBECONFIG를 클러스터 kubeconfig 파일의 경로로 바꿉니다.

출력에서 각 노드의 IPv4 및 IPv6 주소를 확인할 수 있습니다. 노드에서 포드의 IPv4 및 IPv6 주소 범위도 확인할 수 있습니다. 예를 들면 다음과 같습니다.

- apiVersion: v1
  kind: Node
  ...
  spec:
    podCIDR: 192.168.1.0/24
    podCIDRs:
    - 192.168.1.0/24
    - fd12::1:100/120
    providerID: baremetal://10.2.0.5
  status:
    addresses:
    - address: 10.2.0.5
      type: InternalIP
    - address: fd12::2:5
      type: InternalIP

클러스터의 포드를 나열합니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG get pods --all-namespaces

포드 하나를 선택하고 세부정보를 나열합니다. 예를 들면 다음과 같습니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG get pod gke-metrics-agent-b9qrv \
  --namespace kube-system \
  -- output yaml

출력에서 포드의 IPv4 및 IPv6 주소를 확인할 수 있습니다. 예를 들면 다음과 같습니다.

apiVersion: v1
kind: Pod
metadata:
  ...
  name: gke-metrics-agent-b9qrv
  namespace: kube-system
...
status:
  ...
  podIPs:
  - ip: 192.168.1.146
  - ip: fd12::1:11a

ClusterCIDRConfig 사용 변형

앞의 예시에서는 ClusterCIDRConfig 객체를 사용하여 클러스터 전체 포드 CIDR 범위를 지정했습니다. 즉, 단일 IPv4 CIDR 범위는 클러스터의 모든 포드에 사용됩니다. 그리고 단일 IPv6 CIDR 범위가 클러스터의 모든 포드에 사용됩니다.

클러스터의 모든 포드에 단일 CIDR 범위를 사용하지 않으려는 경우가 있습니다. 예를 들어 노드 풀마다 별도의 CIDR 범위를 지정하거나 노드마다 별도의 CIDR 범위를 지정할 수 있습니다.

예를 들어 다음 ClusterCIDRConfig는 "workers"라는 노드 풀의 CIDR 범위를 지정합니다.

apiVersion: baremetal.cluster.gke.io/v1alpha1
kind: ClusterCIDRConfig
metadata:
  name: "worker-pool-ccc"
  namespace: "cluster-dual-stack"
spec:
  ipv4:
    cidr: "192.168.0.0/16"
    perNodeMaskSize: 24
  ipv6:
    cidr: "fd12::1:0/112"
    perNodeMaskSize: 120
  nodeSelector:
    matchLabels:
      baremetal.cluster.gke.io/node-pool: "workers"

다음 ClusterCIDRConfig는 IP 주소가 10.2.0.5인 단일 노드의 CIDR 범위를 지정합니다.

apiVersion: baremetal.cluster.gke.io/v1alpha1
kind: ClusterCIDRConfig
metadata:
  name: "range-node1"
  namespace: "cluster-dual-stack"
spec:
  ipv4:
    cidr: "192.168.1.0/24"
    perNodeMaskSize: 24
  ipv6:
    cidr: "fd12::1:0/120"
    perNodeMaskSize: 120
  nodeSelector:
    matchLabels:
      baremetal.cluster.gke.io/k8s-ip: "10.2.0.5"

ClusterIP 유형의 이중 스택 서비스 만들기

배포 매니페스트는 다음과 같습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: "my-deployment"
spec:
  selector:
    matchLabels:
      app: "try-dual-stack"
  replicas: 3
  template:
    metadata:
      labels:
        app: "try-dual-stack"
    spec:
      containers:
      - name: "hello"
        image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"

매니페스트를 my-deployment.yaml이라는 파일에 저장하고 배포를 만듭니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG apply -f my-deployment.yaml

CLUSTER_KUBECONFIG를 클러스터 kubeconfig 파일의 경로로 바꿉니다.

ClusterIP 유형 서비스의 매니페스트는 다음과 같습니다.

apiVersion: v1
kind: Service
metadata:
  name: "my-service"
spec:
  selector:
    app: "try-dual-stack"
  type: "ClusterIP"
  ipFamilyPolicy: "RequireDualStack"
  ipFamilies:
  - "IPv6"
  - "IPv4"
  ports:
  - port: 80
    targetPort: 8080

이 연습에서 이전 서비스 매니페스트에 대해 알아야 할 핵심 사항은 다음과 같습니다.

  • ipFamilyPolicy 필드가 RequireDualStack으로 설정됩니다. 즉, 서비스에 IPv6 및 IPv4 ClusterIP 주소가 모두 할당됩니다.

  • ipFamilies 필드는 IPv6 그룹을 먼저 지정하고 IPv4 그룹을 두 번째로 지정합니다. 즉, 서비스의 spec.ClusterIP는 클러스터 매니페스트의 clusterNetwork.services.cidrBlocks에서 선택된 IPv6 주소입니다.

매니페스트를 my-cip-service.yaml이라는 파일에 저장하고 서비스를 만듭니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG apply -f my-cip-service.yaml

서비스에 대한 세부정보를 나열합니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG get service my-service --output yaml

출력에서 서비스의 클러스터 IP 주소를 확인할 수 있습니다. 예를 들면 다음과 같습니다.

apiVersion: v1
kind: Service
metadata:
  name: my-service
  …
spec:
  clusterIP: fd12::5:9af
  clusterIPs:
  - fd12::5:9af
  - 172.16.12.197

클러스터 노드에서 서비스를 호출합니다.

curl IPV4_CLUSTER_IP
curl [IPV6_CLUSTER_IP]

출력에 'Hello world' 메시지가 표시됩니다.

Hello, world!
Version: 2.0.0
Hostname: my-deployment-xxx

LoadBalancer 유형의 이중 스택 서비스 만들기

LoadBalancer 유형 서비스의 매니페스트는 다음과 같습니다.

apiVersion: v1
kind: Service
metadata:
  name: "my-lb-service"
spec:
  selector:
    app: "try-dual-stack"
  type: "LoadBalancer"
  ipFamilyPolicy: "RequireDualStack"
  ipFamilies:
  - "IPv6"
  - "IPv4"
  ports:
  - port: 80
    targetPort: 8080

매니페스트를 my-lb-service.yaml이라는 파일에 저장하고 서비스를 만듭니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG apply -f my-lb-service.yaml

클러스터 매니페스트에서 LoadBalancer 유형의 서비스에 사용할 IPv6 주소 범위와 IPv4 주소 범위를 지정했습니다.

  loadBalancer:
    mode: "bundled"
    ...
    addressPools:
    - name: "pool-1"
      addresses:
      - "10.2.0.112-10.2.0.221"
      - "fd12::4:101-fd12::4:110"

IPv4 범위에서 선택한 외부 IPv4 주소와 IPv6 범위에서 선택한 외부 IPv6 주소가 서비스에 할당됩니다.

서비스의 세부정보를 나열합니다.

kubectl --kubeconfig CLUSTER_KUBECONFIG get service my-lb-service --output yaml

출력에서 서비스의 외부 주소를 확인할 수 있습니다. 예를 들면 다음과 같습니다.

apiVersion: v1
kind: Service
metadata:
  name: my-lb-service
...
status:
  loadBalancer:
    ingress:
    - ip: 10.2.0.213
    - ip: fd12::4:101

ipFamilyPolicy에 가능한 값

이중 스택 서비스를 만들 때 ipFamilyPolicy를 다음 값 중 하나로 설정할 수 있습니다.

  • SingleStack: 컨트롤러가 clusterNetwork.services.cidrBlocks에서 클러스터 매니페스트를 지정한 첫 번째 범위에서 선택한 서비스의 클러스터 IP 주소를 할당합니다.

  • PreferDualStack: 컨트롤러는 clusterNetwork.services.cidrBlocks의 클러스터 매니페스트에 지정된 범위에서 선택한 IPv4 및 IPv6 클러스터 IP 주소를 서비스에 할당합니다. 클러스터가 이중 스택 클러스터가 아닌 경우 동작은 SingleStack과 동일합니다.

  • RequireDualStack: 컨트롤러는 clusterNetwork.services.cidrBlocks의 클러스터 매니페스트에 지정된 범위에서 선택한 IPv4 및 IPv6 클러스터 IP 주소를 서비스에 할당합니다. ipFamilies 아래의 서비스 매니페스트에 지정된 첫 번째 주소 그룹을 기반으로 spec.clusterIP 값을 설정합니다.

추가 정보

이중 스택 서비스를 만드는 방법에 대한 자세한 내용은 새 서비스의 이중 스택 옵션을 참조하세요.