0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VM間通信をブリッジアダプタからVXLANに変更する

Last updated at Posted at 2025-10-25

背景

以下の記事で、2台の物理サーバーに、2台ずつVMを作成しそれぞれをKubernets NodeとしてKubernetesクラスタを構築するという記事を書きました。

この時、VM間通信はブリッジアダプタを採用し、VMの仮想NICをホストの物理NICにブリッジし、同じ物理LAN上に載せることでVM同士が L2 で直接通信できるようにしています。

そして、VMの仮想NIC(ここでは enp0s8)には、物理LANのネットワーク上のIPアドレスを割り振っています。

image.png

このやり方で今回は問題ないですが、一般的にはネットワーク構成が物理LANに依存し、ネットワークのスケーラビリティが制限されてしまうという課題があります。

そこで、今回はVLANのスケーラビリティを克服するために開発された、トンネリングベースのオーバーレイ技術であるVXLANを用いてVM間通信を試みようと思います。

そして、本通信手法を用いてKubernetesクラスタを再構築します。

VXLANについて

VXLANを用いると、物理サーバがVMからのL2フレームをL3のUDPパケットにカプセル化し、別の物理サーバに送信することができます。受信側はそれを解除して、目的のVMに届けるといった形の流れになります。

複数の物理サーバで、遠く離れた環境だったとしてもL3ネットワーク設定を気にすることなく通信でき、VM同士は同一のL2上に存在するように振る舞うことができるという点がメリットです。

詳しくは、例えば以下の記事に書かれています。

VXLAN通信の設定

VXLANインターフェース

2台のホスト上で、以下のような設定を追加します。

ここでは、VXLANインターフェースと仮想L2スイッチの設定を行っており、仮想スイッチに接続されたVMからのパケットがVXLANトンネルを通り相手サーバのVMに送られるという経路を作成します。

server-1
REMOTE_HOST_IP="192.168.80.11" # server-2 IP
LOCAL_HOST_IP="192.168.80.10" # server-1 IP
UNDERLAY_IF="eno1" # 物理NIC

VNI=100
# VXLANインターフェース名
VX_NAME="vxlan${VNI}"
# 仮想L2スイッチ名
BR_NAME="br-vxlan"

# 仮想スイッチ作成
sudo ip link add name $BR_NAME type bridge

# VXLANトンネルインターフェースを作成
sudo ip link add $VX_NAME type vxlan id $VNI \
  remote $REMOTE_HOST_IP local $LOCAL_HOST_IP dstport 4789 dev $UNDERLAY_IF

# ブリッジへ接続&有効化
sudo ip link set $VX_NAME master $BR_NAME
sudo ip link set $BR_NAME up
sudo ip link set $VX_NAME up

VM仮想NICの接続先変更

まず、既存の設定を確認します。
VMのNIC2 がホストの物理NIC eno1 に接続されていることが確認できます。(なお、NIC1はVMへのsshのために既に使用されています)

server-1
$ VBoxManage showvminfo "k8s-master" | grep "NIC 2"
NIC 2:    MAC: 0800238162D2, Attachment: Bridged Interface 'eno1', Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported speed: 0 Mbps, Boot priority: 0, Promisc Policy: deny, Bandwidth group: none

NIC2を eno1 に接続し通信できるようにしていましたが、そうではなく、先ほど作成した br-vxlan の仮想スイッチに接続するようにします。

これにより、VMが送信したパケットは br-vxlan の仮想スイッチに届くようになり、br-vxlan がこのパケットを vxlan100トンネルインターフェースに転送することで、VXLANで通信できるようになります。

server-1
VBoxManage modifyvm "k8s-master" --nic2 bridged --bridgeadapter2 "br-vxlan"
VBoxManage modifyvm "k8s-worker-1" --nic2 bridged --bridgeadapter2 "br-vxlan"
server-2
VBoxManage modifyvm "k8s-worker-2" --nic2 bridged --bridgeadapter2 "br-vxlan"
VBoxManage modifyvm "k8s-worker-3" --nic2 bridged --bridgeadapter2 "br-vxlan"

本設定を行った後、接続先が eno1 から br-vxlan に更新されていることを確認します。

server-1
server-1:~$ VBoxManage showvminfo "k8s-master" | grep "NIC 2"
NIC 2:      MAC: 0800238162D2, Attachment: Bridged Interface 'br-vxlan', Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported speed: 0 Mbps, Boot priority: 0, Promisc Policy: allow-all, Bandwidth group: none

プライベートIPを仮想NICに設定

各VMにおける既存の enp0s8 (NIC2) のIPアドレスは、アンダーレイネットワーク(物理LAN)のIPであり、VXLANはオーバーレイネットワークであるため、重複しないプライベートなIPネットワークに変更します。

/etc/netplan/01-bridged.yaml のadressを、以下のように修正しました。

  • k8s-master
    • 192.168.80.101/24→10.10.10.101/24
  • k8s-worker-1
    • 192.168.80.103/24→10.10.10.103/24
  • k8s-worker-2
    • 192.168.80.105/24→10.10.10.105/24
  • k8s-worker-3
    • 192.168.80.107/24→10.10.10.107/24

設定反映後、各VMの enps08 に割り当てられるIPアドレスがプライベートIPに変更させれていることを確認します。

k8s-master
$ ip a show enp0s8
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:92:62:c2 brd ff:ff:ff:ff:ff:ff
    inet 10.10.10.101/24 brd 10.10.10.255 scope global enp0s8
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe92:62c2/64 scope link 
       valid_lft forever preferred_lft forever

ここまでの設定で、オーバーレイネットワークとしては以下の構成になります。

image.png

このように、VMは物理LANのIPアドレスを意識することなく、10.10.10.x というプライベートIPだけで通信できるのがVXLANの大きなメリットです。

なお、実際はパケットがカプセル化された状態で、物理LANのアンダーレイネットワークを通っている点を補足します。

動作確認

ping

まず、先ほど設定したプライベートIPを利用して、VM間でpingが通ることを確認します。
以下は、k8s-worker-3のVMからk8s-masterのVMにpingを飛ばした例で、通信できていることが確認できます。

k8s-worker-3
$ ping 10.10.10.101
PING 10.10.10.101 (10.10.10.101) 56(84) bytes of data.
64 bytes from 10.10.10.101: icmp_seq=1 ttl=64 time=2.50 ms
64 bytes from 10.10.10.101: icmp_seq=2 ttl=64 time=1.44 ms
64 bytes from 10.10.10.101: icmp_seq=3 ttl=64 time=1.30 ms
^C
--- 10.10.10.101 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms

tcpdumpによるVXLANの確認

上記のpingを実行しながら、k8s-master VMのホストであるserver-1上でtcpdumpを行いパケットを眺めます。

k8s-worker-3 (10.10.10.107) からの ping 要求が、server-2(192.168.80.11)によってカプセル化され、server-1(192.168.80.10)のポート 4789 宛に、VXLAN パケット(vni 100)として送信されていることがわかります。

server-1
$ sudo tcpdump -i eno1 -n udp port 4789

03:44:37.161493 IP 192.168.80.11.58425 > 192.168.80.10.4789: VXLAN, flags [I] (0x08), vni 100
IP 10.10.10.107 > 10.10.10.101: ICMP echo request, id 3, seq 22, length 64

本ログにより、オーバーレイネットワーク(10.10.10.x)上の ICMP通信が、アンダーレイネットワーク(192.168.80.x)上で UDP/4789 にカプセル化されている様子が確認できました。

外部ネットワークとの接続

nic2 (enp0s8)の接続先を、閉じた仮想ネットワークである br-vxlan に変更したため通信がネットワークに出れなくなってしまっていたという問題が発生しました。

そのため、インターネット専用の3つ目のNIC(NAT)を追加します。

server-1, server-2
VBoxManage modifyvm "k8s-master" --nic3 nat
VBoxManage modifyvm "k8s-worker-1" --nic3 nat
VBoxManage modifyvm "k8s-worker-2" --nic3 nat
VBoxManage modifyvm "k8s-worker-3" --nic3 nat

NIC3の設定を、以下のsudo vim /etc/netplan/02-nat.yaml で作成し、sudo netplan apply で反映します。

ここでは、各VM内部で、enp0s9 をDHCPで自動設定しています。つまり、NAT機能によりIPアドレスとデフォルトゲートウェイを自動で取得できるようにします。

network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s9:  # NIC3 に対応するインターフェース名
      dhcp4: true

実行後、ping 8.8.8.8 が通ることを確認し、外部ネットワークに接続できているようになりました。

Kubernetesクラスタ再構築

VM間通信にVXLANを利用できるように設定したところで、Kubernetesクラスタを再構築したいと思います。主に、Node IPを変更する形になります。

swapoffの確認

sudo swapoff -a

Node IPの再設定

k8s-master
echo 'KUBELET_EXTRA_ARGS=--node-ip=10.10.10.101' | sudo tee /etc/default/kubelet
sudo systemctl restart kubelet
k8s-worker-1
echo 'KUBELET_EXTRA_ARGS=--node-ip=10.10.10.103' | sudo tee /etc/default/kubelet
sudo systemctl restart kubelet
k8s-worker-2
echo 'KUBELET_EXTRA_ARGS=--node-ip=10.10.10.105' | sudo tee /etc/default/kubelet
sudo systemctl restart kubelet
k8s-worker-3
echo 'KUBELET_EXTRA_ARGS=--node-ip=10.10.10.107' | sudo tee /etc/default/kubelet
sudo systemctl restart kubelet

Master Nodeにて、kubeadmをリセットし再構築します。

k8s-master
sudo kubeadm reset -f
sudo systemctl restart containerd || true
sudo kubeadm init \
  --apiserver-advertise-address=10.10.10.101 \
  --pod-network-cidr=10.244.0.0/16

kubectl

k8s-master
mkdir -p $HOME/.kube
sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

CNI(Flannel)

k8s-master
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/v0.27.4/Documentation/kube-flannel.yml

各Worker Nodeでは、joinを行います。

sudo kubeadm reset -f
sudo systemctl restart kubelet
sudo kubeadm join 10.10.10.101:6443 --token <token> \
	--discovery-token-ca-cert-hash sha256:<hash>

最後に、クラスタのNode構成を確認します。

$ kubectl get nodes
NAME           STATUS   ROLES           AGE     VERSION
k8s-master     Ready    control-plane   4h31m   v1.31.13
k8s-worker-1   Ready    <none>          4h20m   v1.31.13
k8s-worker-2   Ready    <none>          3h47m   v1.31.13
k8s-worker-3   Ready    <none>          3h41m   v1.31.13

まとめ

本記事では、ブリッジアダプタを用いたVM間通信の構成から、VXLANを用いた通信に変更してみました。その上で、Kubernetesクラスタを再構築してみました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?