背景
研究室に、誰も使用していない物理サーバーが5台ほどあった(!!)ので、そのうち2台を使って以前から個人的にやってみたかったKubernetesクラスタの構築を行ってみました。
ローカルのPCから研究室のサーバーで構成されたKubernetesクラスタに対し、kubectlが通りることをゴールにしてそこまでの設定についてブログという形でまとめてみようと思います。
Virtual BoxによりVMを各物理サーバーに2台ずつ作成し、Master Node1台、Worker Node3台の構成で構築しました。
ほぼ個人用の備忘録ですが、同じようなことをやろうとしている人に対する参考になれば幸いです。
物理サーバについて
スペック
- マシン: Dell OptiPlex 9020
- CPU: 4コア8スレッド
- RAM: 8G
- ディスク: 100G
接続方法
学内VPNに繋いだ状態でLANケーブルをスイッチに挿した後に得られるIPアドレスに対してローカルからssh接続を行うことで、リモートからでも物理サーバーに接続できるようになりました。
VMの設定について
VirtualBoxの利用
ProxmoxによるVM管理は魅力的でしたが、物理サーバーにはすでにUbuntuがインストールされており、既存のホストOSを削除してまでProxmoxを導入するのはリスクが高いと判断しました(一応研究室の共用サーバーなので)。
そのため、既存環境を壊さずに安全にVMを構築できるVirtualBoxを採用しました。
初期設定
以下のサイトを参照しながら操作を行いました。
VM作成(1台のみ)
まず、1台だけ仮想マシンを作成していきます。ここではMaster Nodeに使用するVMとします。残りのWorker Node用のVM3台については、下記の作業を再度行うのが面倒なので、後述するVMのcloneにより作成します。
VirtualBox本体と拡張パックをインストール
sudo apt update
sudo apt install -y virtualbox virtualbox-ext-pack
Ubuntu Server 22.04 のISOイメージをダウンロード
wget https://releases.ubuntu.com/22.04/ubuntu-22.04.5-live-server-amd64.iso
変数としてVM名・ディスクパス・ISOパスを設定(Master Nodeで使用するVMの設定)
VM_MASTER_NAME="k8s-master"
VM_DISK_PATH="$HOME/virtualbox_vms/${VM_MASTER_NAME}.vdi"
OS_ISO_PATH="$HOME/ubuntu-22.04.5-live-server-amd64.iso"
Ubuntu 64bit 用の新しい仮想マシンを作成・登録
VBoxManage createvm --name "${VM_MASTER_NAME}" --ostype "Ubuntu_64" --register
仮想マシンにメモリ4GB・CPU4コアを割り当て、30GBの仮想ハードディスクを作成
VBoxManage modifyvm ${VM_MASTER_NAME} --memory 4096 --cpus 4
VBoxManage createhd --filename "${VM_DISK_PATH}" --size 30000
SATAコントローラを追加し、その上に仮想ハードディスクとUbuntuのインストール用ISOを接続
VBoxManage storagectl "${VM_MASTER_NAME}" --name "SATA Controller" --add sata --controller IntelAhci
VBoxManage storageattach "${VM_MASTER_NAME}" --storagectl "SATA Controller" --port 0 --device 0 --type hdd --medium "${VM_DISK_PATH}"
VBoxManage storageattach "${VM_MASTER_NAME}" --storagectl "SATA Controller" --port 1 --device 0 --type dvddrive --medium "${OS_ISO_PATH}"
リモートデスクトップ(RDP)の設定
ここまでの設定で作成したVMは、まだ空の状態です。
そのため、OSが入っておらずOpenSSHもインストールされておらず、アクセスしてこれらの設定を行うためにはリモートデスクトップ(RDP)を使用する必要があります。
VirtualBoxのRDP機能(VRDE)を有効にしてポートの設定さえ行えばGUIでVMに接続でき、OS等をインストールできるようになります。
私はWindows AppをRDPとして利用しました。
RDP機能(VRDE)の有効化:
VBoxManage modifyvm "k8s-master" --vrde on
Windows AppでのVM一覧表示
Windows Appの各VMの設定において対象のIPアドレスを入力し接続を行います。
接続できたら、GUIの案内に従ってセットアップを行なっていけば大丈夫です。
clone設定
同一物理サーバー内のclone
前述したように、Worker用のVMについては、毎回OSをインストールしたりするのは大変なので、MasterのVMをcloneする形で作成を行います。
以下は、k8s-masterという作成済みのVMから、k8s-worker-1という同じ設定のVMを新たに作成する処理になります。
VBoxManage controlvm k8s-master acpipowerbutton
VBoxManage clonevm k8s-master --name k8s-worker-1 --register
VBoxManage startvm k8s-worker-1 --type headless
なお、先述したリモートデスクトップでの接続を行うためにデフォルトの3389ポートが使われている場合に、別のポートを利用できるようにしておき、RDP機能(VRDE)を有効化しておく必要があります。
VBoxManage modifyvm "k8s-worker-1" --vrde on
VBoxManage modifyvm "k8s-worker-1" --vrdeport 3390
物理サーバーを跨いだclone処理
例えば、物理サーバー1(server-1と呼ぶことにします)のk8s-worker-1というVMと同じ設定のVMを、物理サーバー2(server-2と呼ぶことにします)にも作成したい場合、以下のように、exportした仮想マシンファイル(OVA)をscpにより転送し、importすれば良いです。
これにより、server-2においてclone処理だけでOSの入ったVMであるk8s-worker-2とk8s-worker-3が作成できます。
VBoxManage controlvm k8s-worker-1 poweroff
VBoxManage export k8s-worker-1 -o k8s-worker-1.ova
scp k8s-worker-1.ova server-2@<IP>:~/
VBoxManage import k8s-worker-1.ova --vsys 0 --vmname k8s-worker-2
VBoxManage import k8s-worker-1.ova --vsys 0 --vmname k8s-worker-3
VBoxManage startvm k8s-worker-2 --type headless
VBoxManage startvm k8s-worker-3 --type headless
clone後のVMにsshできるようにするための設定(RDP)
cloneしたVMについて、ホスト名の設定とマシンIDの重複を避けるために以下の設定を反映する必要があります。
対象のVMに対してWindows App経由で接続し、以下を実行しました。
sudo hostnamectl set-hostname k8s-worker-2
sudo truncate -s 0 /etc/machine-id
sudo rm /var/lib/dbus/machine-id
sudo dbus-uuidgen --ensure=/etc/machine-id
sudo ln -s /etc/machine-id /var/lib/dbus/machine-id
sudo reboot
NIC(ネットワークアダプタ)の設定
マシン内でVMが通信できるよう設定
同一物理サーバー上のVM同士が相互に通信できるようにするために、以下のNICを追加します。
- host only: 同一サーバー内のVM同士およびホストOSとの通信を行うためのプライベートなL2ネットワーク
ホストOS側に Host-only用の仮想NIC vboxnet0 を作成
VBoxManage hostonlyif create
各VMのNIC1をHost-onlyとし、仮想NIC vboxnet0 に繋げる
VBoxManage modifyvm "${VM_MASTER_NAME}" \
--nic1 hostonly --hostonlyadapter1 vboxnet0
この設定により、VMは vboxnet0 を介して同一ホスト上のVMやホストOSと直接通信可能となります。
なお、hostonlyの通信を示した図は以下のようになります。
hostonlyネットワークの設定確認
上記の設定が反映されているかどうかは、例えばL2で直接通信可能な同一ブロードキャストドメイン内のアドレスを表示するARPテーブルにより、以下のように確認することができます。
ping -c 1 192.168.56.103 を実行(k8s-master→k8s-worker-1) 後、k8s-master上でarpを実行すると、k8s-worker-1のenp0s3 (192.168.56.103)が表示されており、VM同士が直接接続できていることがわかります。
$ arp -n
192.168.56.103 ether 08:00:27:6b:85:47 C enp0s3
k8s-master(192.168.56.101)からk8s-worker-2(192.168.56.105)は別の物理マシンなのでping -c 1 192.168.56.105が通らないことを確認します。ARPテーブルにも表示されません。
$ ping -c 1 192.168.56.105
PING 192.168.56.105 (192.168.56.105) 56(84) bytes of data.
From 192.168.56.101 icmp_seq=1 Destination Host Unreachable
--- 192.168.56.105 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
以下のように、物理マシン上で共通の仮想インターフェース vboxnet0を通じてk8s-masterとk8s-worker-1が繋がっていることを確認することもできます。
- 仮想スイッチ
vboxnet0が各VMのenp0s3を相互に接続しており、それによって同一物理サーバー上のVM間通信が成立している、と判断できます。
$ VBoxManage showvminfo "k8s-master" | grep "NIC 1"
NIC 1: MAC: 08002735F5B1, Attachment: Host-only Interface 'vboxnet0', Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported speed: 0 Mbps, Boot priority: 0, Promisc Policy: deny, Bandwidth group: none
$ VBoxManage showvminfo "k8s-worker-1" | grep "NIC 1"
NIC 1: MAC: 0800276B8547, Attachment: Host-only Interface 'vboxnet0', Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported speed: 0 Mbps, Boot priority: 0, Promisc Policy: deny, Bandwidth group: none
なお、物理サーバーを跨いだVM間の通信(Master NodeとWorker Nodeの通信)を行うためには上記の設定では不十分で、Bridgedアダプタを追加して、VMを物理LAN上と同じネットワークに接続する必要があります。
物理サーバーを跨いだVM間の通信
Kubernetesクラスタ構築には、別物理サーバー上のVM間通信が不可欠です。
両物理サーバーは同一物理LAN (192.168.80.0/24) にいるため、VirtualBoxのBridgedアダプタを利用します。VMのNIC2をホストの物理NIC (eno1) にブリッジし、VMを物理LANへL2レベルで直接接続するようにします。
これにより、異なる物理サーバー上のVM同士が、同じL2ネットワーク上の物理マシンのように直接通信できます。
VBoxManage modifyvm "k8s-master" --nic2 bridged --bridgeadapter2 "eno1"
VBoxManage modifyvm "k8s-worker-1" --nic2 bridged --bridgeadapter2 "eno1"
VBoxManage modifyvm "k8s-worker-2" --nic2 bridged --bridgeadapter2 "eno1"
VBoxManage modifyvm "k8s-worker-3" --nic2 bridged --bridgeadapter2 "eno1"
新たなNICに対して物理LANのサブネット範囲内でIPアドレスを割り振っていきます。以下は、図ではk8s-masterのVMに対応した設定例です。
sudo vim /etc/netplan/01-bridged.yaml
network:
version: 2
renderer: networkd
ethernets:
enp0s8:
dhcp4: no
addresses: [192.168.80.101/24]
gateway4: 192.168.80.1
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
sudo netplan apply
図では以下のようになります。別の物理サーバー上のVMがBridgedアダプタにより、ホストのeno1に接続された物理LAN(192.168.80.0/24)を通じて通信できるようになります。
仮想ブリッジの設定確認
仮想ブリッジの動作確認も行ってみます。ping -c 1 192.168.80.105 等を行った後にARPテーブルを確認すると、enp0s8 が登録されていることがわかります。
$ arp -n
192.168.80.105 ether 08:00:27:a4:45:d0 C enp0s8
192.168.80.107 ether 08:00:27:9f:d6:44 C enp0s8
192.168.80.103 ether 08:00:27:78:53:ee C enp0s8
また、各VMはeno1に繋がっていることも確認できます。
$ VBoxManage showvminfo "k8s-master" | grep "NIC 2"
NIC 2: MAC: 0800279262C2, 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
$ VBoxManage showvminfo "k8s-worker-1" | grep "NIC 2"
NIC 2: MAC: 0800277853EE, 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
$ VBoxManage showvminfo "k8s-worker-2" | grep "NIC 2"
NIC 2: MAC: 080027A445D0, 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
$ VBoxManage showvminfo "k8s-worker-3" | grep "NIC 2"
NIC 2: MAC: 0800279FD644, 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
これにより、VirtualBoxのブリッジ機能によって、各VMの仮想NIC enp0s8 がホストの物理NIC eno1 に仮想的に直結され、物理サーバーが異なっていても全てのVMが同一の物理LAN上で直接通信できる状態にあることが確認できました。
動作確認・後編について
.ssh/config に物理サーバー及び仮想マシンのIPアドレスを設定し、ssh k8s-master といった形でリモートから接続できることを各VMについて確認できました。
ここまで出来てようやく、kubeadmによりKubernetesクラスタを構築するための土台が完成したので、後編の記事についてはそのためのセットアップ方法について説明したいと思います。
後編は、以下に続きます。


