ProxmoxでおうちKubernetes環境を作った
お正月なので
使っていないPCにProxmoxを入れて、おうちKubernetes環境を構築しました。
余ってたPCにProxmox入れておうちk8s環境ができたので喜びの舞 pic.twitter.com/Yh03sp2wek
— ser1zw (@ser1zw) January 2, 2025
構成
Proxmox上の仮想マシン(Ubuntu)でKubernetesを動かします。 Kubernetesのノードはコントロールプレーン1台、ワーカーノード2台という構成とします。

- Proxmox用PC
- 仮想化環境:
- Kubernetes環境
- Kubernetes本体: Kubernetes 1.32
- コンテナランタイム: cri-o 1.32
- CNIプラグイン: Calico 3.29.1
- ホストOS: Ubuntu Server 24.04.1 LTS
仮想マシンのスペック
スペックはコントロールプレーン、ワーカーノード共通で下記のとおり。
- CPU: 1ソケット2コア
- メモリ: 4GB
- ディスク: 32GB
各マシンのホスト名およびIPアドレス
- Proxmox
pve: 192.168.50.10
- Kubernetesコントロールプレーン
k8s-controlplane-01: 192.168.50.11
- Kubernetesワーカーノード
k8s-workernode-01: 192.168.50.12k8s-workernode-02: 192.168.50.13
- KubernetesのPod用セグメント: 172.16.0.0/12
構築
方針
- ProxmoxよくわかんないのでひとまずGUIでVMを作ります。本当は Terraform とか cloud-init とか Ansible とかでやりたいけどそれはまた今度。
- Kubernetesもよくわかんないのでおとなしく
kubeadmで作ります。 - セキュリティ面は見なかったことにします。各自いい感じにやってくれ。
構築手順
1. Proxmoxのセットアップ
まずはProxmoxのISOファイルを このへん からダウンロードしてきます。
ダウンロードできたら、そのへんのUSBメモリに書き込めばOK。dd コマンドでやるならだいたいこんな感じ。
$ sudo dd if=./proxmox-ve_8.3-1.iso of=/dev/sdc status=progress bs=1KB
USBメモリができあがったらPCに挿してUSBブートすればインストーラが起動するので、あとはインストーラにしたがって進めていけばOK。
インストールが終わったらPCを再起動するとProxmoxにログインできるようになるので、PCにディスプレイとキーボードを挿したり別の端末からブラウザでWeb UI https://192.168.50.10:8006/ にアクセスしたりしていじります。
なお、このタイミングでProxmoxのサブスクリプション無し版リポジトリの追加&アップデートをしておくとよいです。
左メニューのDatacenter配下のノードを選択して Update > Repositories を開き、Add ボタンから Repository: No-Subscription を追加します。
ついでにEnterpriseっぽい https://enterprise.proxmox.com/debian/ceph-quincy と https://enterprise.proxmox.com/debian/pve を選択して Disable で無効化し、 Repositories の上の Updates メニューで Refresh、Upgrade していけばOKです。


2. Kubernetesノード用のVM構築
ProxmoxのWeb UI https://192.168.50.10:8006/ から作成していきます。
と言っても基本的には画面右上の Create VM ボタンからぽちぽちやっていくだけです。
変えたのは下記項目。その他はデフォルトのまま。
| タブ | 項目名 | 値 |
|---|---|---|
| General | Name | ホスト名(k8s-controlplane-01, k8s-workernode-01, k8s-workernode-02) |
| OS | Use CD/DVD disc image file (iso) > ISO image | UbuntuのISOイメージ(事前に左メニュー local > ISO Images からアップロードしておく) |
| CPU | Cores | 2 |
| CPU | Type | host |
| Memory | Memory (MiB) | 4096 |

あとはVMを起動し、 Console からインストールしていけばOK。
これをコントロールプレーン用1台、ワーカーノード用2台の計3台分行います。
3. Kubernetesコントロールプレーンの構築
ProxmoxのコンソールまたはsshでコントロールプレーンのVM k8s-controlplane-01 内から操作していきます。
3-1. インストール前の事前準備
何はなくともまずは諸々アップデート
$ sudo apt-get update && sudo apt-get upgrade -y && sudo apt-get autoremove -y && sudo apt-get autoclean -y
スワップをOFFにします。永続化のため、 /etc/fstab で # /swap.img 〜 の行を削除orコメントアウトしておきます。
$ sudo swapoff -a $ sudo vi /etc/fstab # /swap.img none swap sw 0 0 # 削除orコメントアウト
cat /proc/swaps でスワップの内容が表示されなくなることを確認。
$ cat /proc/swaps Filename Type Size Used Priority
カーネルモジュール br_netfilter の有効化と、カーネルパラメータ net.ipv4.ip_forward の設定を行います。
$ echo "br_netfilter" | sudo tee /etc/modules-load.d/k8s.conf $ echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/k8s.conf $ sudo sysctl --system
3-2. cri-o, Kubernetesのインストール
だいたい cri-oのREADME の記載に従って進めていきます。
まずはバージョンを環境変数に入れておき…
$ KUBERNETES_VERSION=v1.32 $ CRIO_VERSION=v1.32
cri-o, Kubernetesのリポジトリを追加して apt-get でインストール。
$ curl -fsSL https://pkgs.k8s.io/core:/stable:/$KUBERNETES_VERSION/deb/Release.key |
sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
$ echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/$KUBERNETES_VERSION/deb/ /" |
sudo tee /etc/apt/sources.list.d/kubernetes.list
$ curl -fsSL https://pkgs.k8s.io/addons:/cri-o:/stable:/$CRIO_VERSION/deb/Release.key |
sudo gpg --dearmor -o /etc/apt/keyrings/cri-o-apt-keyring.gpg
$ echo "deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://pkgs.k8s.io/addons:/cri-o:/stable:/$CRIO_VERSION/deb/ /" |
sudo tee /etc/apt/sources.list.d/cri-o.list
$ sudo apt-get update
$ sudo apt-get install -y cri-o kubelet kubeadm kubectl
インストールが完了したら、意図しないバージョンアップを避けるためバージョンを固定しておきます。
$ sudo apt-mark hold cri-o kubelet kubeadm kubectl
cri-o のサービスを立ち上げておき…
$ sudo systemctl start crio.service
念のためVMを再起動。
$ sudo shutdown -r now
3-3. コントロールプレーン構築
起動したら再度VMに入り、いよいよKubernetesのコントロールプレーンを構築していきます。
kubeadm コマンドにPod用ネットワークセグメント 172.16.0.0/12 を渡して実行。
$ sudo kubeadm init --pod-network-cidr=172.16.0.0/12
成功すると下記のようなメッセージが表示されます。最後の kubeadm join コマンドはワーカーノード作成時に使うので、忘れずに控えておきます。
Your Kubernetes control-plane has initialized successfully!
(中略)
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.50.11:6443 --token ******.**************** \
--discovery-token-ca-cert-hash sha256:****************************************************************
3-4. kubectl コマンド用の設定
$ mkdir -p $HOME/.kube $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config $ sudo chown $(id -u):$(id -g) $HOME/.kube/config
これで kubectl get pods とかできるようになります。
3-5. Calicoのインストール
今回はCNIプラグインとしてCalicoを使います。インストールの流れはほぼ Calicoのドキュメント のとおりでOK。
まずはCalicoのマニフェストをダウンロードします。
$ wget https://raw.githubusercontent.com/projectcalico/calico/v3.29.1/manifests/tigera-operator.yaml $ wget https://raw.githubusercontent.com/projectcalico/calico/v3.29.1/manifests/custom-resources.yaml
ここで1点注意。custom-resources.yaml にはPodのネットワークセグメントが 192.168.0.0/16 と直接書かれているので、今回のネットワークセグメントに合わせて書き換える必要があります。
$ vi custom-resources.yaml
# cidr: 192.168.0.0/16 # 削除orコメントアウト
cidr: 172.16.0.0/12 # 追加
編集が終わったら kubectl create でデプロイします。
$ kubectl create -f tigera-operator.yaml $ kubectl create -f custom-resources.yaml
しばらく待って、 kubectl get nodes で STATUS が Ready に、kubectl get pods -A で全Podの STATUS が Running になれば完了です。
4. Kubernetesワーカーノードの構築
ワーカーノードのVM k8s-workernode-01、k8s-workernode-02 で操作していきます。
まずは 3. kubernetesコントロールプレーンの構築 の最初から 3-2. cri-o, Kubernetesのインストール まで、コントロールプレーンと同じ手順で進めます。
完了後、3-3. コントロールプレーン構築 の最後で控えた kubeadm join コマンドを実行すればノードがクラスタに追加されます。
$ sudo kubeadm join 192.168.50.11:6443 --token ******.**************** \
--discovery-token-ca-cert-hash sha256:****************************************************************
コントロールプレーンのVMで kubectl get nodes を実行し、ワーカーノードが表示されていればOK。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-controlplane-01 Ready control-plane 16h v1.32.0 k8s-workernode-01 Ready <none> 16h v1.32.0 k8s-workernode-02 Ready <none> 16h v1.32.0
試してみる
コントロールプレーン k8s-control-plane-01 でこんな感じのyamlを用意しておき…
# nginx.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: selector: matchLabels: app: nginx replicas: 1 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.27.3 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: type: NodePort ports: - port: 8080 targetPort: 80 nodePort: 30080 protocol: TCP selector: app: nginx
# toolbox.yaml # https://github.com/ser1zw/toolbox-container apiVersion: v1 kind: Pod metadata: name: toolbox spec: containers: - name: toolbox image: ser1zw/toolbox:latest
デプロイします。
$ kubectl apply -f nginx.yaml $ kubectl apply -f toolbox.yaml
nginxに別のPodからcurlでアクセスすると、正常に応答が返ってきます。いい感じ。
$ kubectl exec toolbox -- curl -s nginx:8080 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> (中略) </html>
ついでに上記マニフェストではServiceをNodePortにしているので、ホストマシンと同一ネットワーク上の別端末からノードのIPを指定してcurlを実行しても(ファイヤウォールが開いていれば)応答が返ってきます。
$ curl -s 192.168.50.12:30080 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> (中略) </html>
完璧ですね。
まとめ
というわけで、無事おうちKubernetes環境が構築できました。
今回は手動でGUI操作したりコマンド実行したりしましたが、何台もあるとめんどくさいのでIaC化しておきたいところです。