仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

KubernetesクラスターでIPv4/IPv6 Dual-stackサポートを有効にする

Kubernetes(正確にはクラスタネットワーク)はデフォルト設定はIPv4のアドレスのみを利用するようです。 とある案件で必要になったため、KubernetesのIPv6周りを調べることにしました。 今回の内容は3回に分けてブログにしようと思います。

内容

要件

今回は手元の環境の次の構成でテストしました。

  • Ubuntu Server 22.04 LTS

    • Kubernetes 1.25.0
    • CRI: containerd 1.5.9
    • CNI: Calico
    • IPv4/IPv6 Dual-stack
  • Fedora 36

    • Kubernetes 1.25.0
    • CRI: CRI-O 1.24
    • CNI: Calico
    • IPv4/IPv6 Dual-stack

kubeadmで構築するKubernetesのデフォルト構成ではIPv4アドレスがデフォルトで使われます(実際はCNIプラグインの実装、設定も絡む)。今回のような方法でIPv4/IPv6 Dual-stackなクラスターとしてセットアップできます。

ちなみに、IPv6 Onlyについてはやり方はあるようですが、IPv6 Onlyのクラスターの実用上はどうかと言われると微妙なのかなと思います。

kubeadmによるクラスタ作成

IPアドレスを確認します。

$ ip addr show enp0s6 
    inet 192.168.205.111/24 brd 192.168.205.255 scope global dynamic noprefixroute enp0s6
       valid_lft 85665sec preferred_lft 85665sec
    inet6 fd7e:8daa:f56:3f94:ac5e:d2ff:fe71:ee0e/64 scope global dynamic noprefixroute 
       valid_lft 2591996sec preferred_lft 604796sec
    inet6 fe80::ac5e:d2ff:fe71:ee0e/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

自宅環境ではIPv6アドレスをインターネットアクセスでは使っていない(インターネットサービスがIPv6を提供していない)ため、以下ではすべてリンクローカルユニキャストアドレスを使っています。この手順に従いIPv4/IPv6 DualStackなKubernetesクラスターを構築できますが、結局IPv6経由でインターネット側に出られない格好になるので、ご注意ください(IPv6 Readyなネットワークにいればグローバルユニキャストアドレスが割り振られているはずですから、それを使えばテストできるでしょう)。

hostsに調べたアドレスをそれぞれ書いておきます(当然ながら本番ではDNSで名前解決できるように設定します)。

$ sudo vi /etc/hosts
...
192.168.205.111 k8s.example.com
 fd7e:8daa:f56:3f94:ac5e:d2ff:fe71:ee0e k8s.example.com

OS、コンテナランタイムの設定、kubeadm,kubeletツールのインストールと設定は通常通り実施します。 Firewallでポートが閉じられている場合は、最低限次のポートは開放する必要があります。

  • 6443/tcp
  • 10250/tcp
  • 30000-32767/tcp

クラスターの作成はCreating a cluster with kubeadmに従って、CIDRをIPv4とIPv6のアドレスを指定します。

control-plane-endpointは今回はhostsに書いたIPv4/IPv6アドレスの関連付けしたドメインを記述します。

$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16,2001:db8:42:0::/56 --service-cidr=10.96.0.0/16,2001:db8:42:1::/112 --control-plane-endpoint=k8s.example.com

Calicoをインストール

Quickstart for Calico on Kubernetesを開いて、それぞれダウンロードします。カスタムリソースの方はダウンロードしたあと、IPv6周りの設定の追記をします。

執筆日(2022年9月6日)時点では3.24.1が最新の安定版のようです。

$ wget https://raw.githubusercontent.com/projectcalico/calico/v3.24.1/manifests/tigera-operator.yaml
$ wget https://raw.githubusercontent.com/projectcalico/calico/v3.24.1/manifests/custom-resources.yaml

custom-resources.yamlの変更内容

IPv4のCIDRのレンジの修正とIPv6のCIDRの追記を行います。記述するのはkubeadm initで指定したものを記述します。 IPv4のCIDRはデフォルトが「192.168.0.0/16」が設定されているため、同様に指定したCIDRに書き換えます。 それ以外の部分は触らずにエディタを終了します。

$ cat custom-resources.yaml 
# This section includes base Calico installation configuration.
# For more information, see: https://projectcalico.docs.tigera.io/master/reference/installation/api#operator.tigera.io/v1.Installation
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
spec:
  # Configures Calico networking.
  calicoNetwork:
    # Note: The ipPools section cannot be modified post-install.
    ipPools:
    - blockSize: 26
      cidr: 10.244.0.0/16
      encapsulation: VXLANCrossSubnet
      natOutgoing: Enabled
      nodeSelector: all()
    - blockSize: 122
      cidr: 2001:db8:42:0::/56
      encapsulation: None
      natOutgoing: Enabled
      nodeSelector: all()
---

# This section configures the Calico API server.
# For more information, see: https://projectcalico.docs.tigera.io/master/reference/installation/api#operator.tigera.io/v1.APIServer
apiVersion: operator.tigera.io/v1
kind: APIServer 
metadata: 
  name: default 
spec: {}

設定をクラスターに適用します。

$ kubectl create -f  tigera-operator.yaml 
$ kubectl create -f  custom-resources.yaml

動作確認

自宅はIPv6 Readyではないので、VMでLinuxを動かしてホストのIPv6アドレスはユニキャストアドレスを使っています。クラスターに割り当てているIPv6アドレスは実行例そのままです(ちなみに2022年中に新たにIPv6サービスを提供するとか聞いているので楽しみだったりします)。

ノードにPod CIDRとして、IPv4とIPv6レンジが設定されているのを確認します。

$ kubectl get node fedora -o go-template --template='{{range .spec.podCIDRs}}{{printf "%s\n" .}}{{end}}'
10.244.0.0/24
2001:db8:42::/64

試しにPodを作成します。

$ cat testpod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: hello-rhubi9
spec:
  containers:
    - name: ubi9
      image: docker.io/redhat/ubi9:latest
      tty: true
      
$ kubectl create -f testpod.yaml 

作成したPodにもIPv4とIPv6のアドレスが割り当てられます。

$ kubectl get -f testpod.yaml -o go-template --template='{{range .status.podIPs}}{{printf "%s\n" .ip}}{{end}}'
10.244.78.142
2001:db8:42:c5:45e3:dcb6:dab7:e24d

とりあえず、Podを作成すると、PodにIPv4とIPv6のアドレスが割り当てられました。 今回はここまでです。次回に続きます。