お家KubernetesをProxmoxで作り直した
経緯
以前の記事ででお家 kubernetes を構築し色々遊んでいました。 楽しくなってきたので新しい PC を購入しクラスターに追加しようと、何も考えず kubespray を動かすと etcd 周りでエラーが起きてしまったらしく 追加することができませんでした。 そこで、これもいい機会ということで前から気になっていた Proxmox という仮想化環境で kubernetes を作り直しました。 この記事はその作業ログをまとめたものです。
環境
- 仮想化環境: Proxmox VE 8.0.3
- 使用したイメージ: Ubuntu Server 22.04
- CRI: CRI-O
- CNI: Calico
- control plane: 1 台
- node: 3 台
VM 作成
まず、kubernetes のベースとなる VM を作成します。上で紹介したように Ubuntu Server 22.04 を利用します。 Proxmox のインストールについては、多くの解説記事が存在するのでそちらをご覧ください。 今回は以下の設定で作成し、インストール時のオプションは SSH のみ有効にし、それ以外はデフォルトで設定しました。 この部分については各自の環境に合わせて調整してください。

作成が完了したら、パッケージを更新しておきます
sudo apt updatesudo apt upgrade -yIPv4 フォワーディング有効化
以下のコマンドを実行します。
cat <<EOF | sudo tee /etc/modules-load.d/k8s.confoverlaybr_netfilterEOF
sudo modprobe overlaysudo modprobe br_netfilter
# この構成に必要なカーネルパラメーター、再起動しても値は永続しますcat <<EOF | sudo tee /etc/sysctl.d/k8s.confnet.bridge.bridge-nf-call-iptables = 1net.bridge.bridge-nf-call-ip6tables = 1net.ipv4.ip_forward = 1EOF
# 再起動せずにカーネルパラメーターを適用sudo sysctl --system正直何をしているか全然わかっていないので、周りの詳しい方に聞いたほうが良いと思います。一応 ChatGPT に聞いてみたら下のように返してきました

このコマンドを実行して必要なモジュールが正しくロードされていることを確認します
lsmod | grep br_netfilterlsmod | grep overlayswap の無効化
前提条件として必要なので swap を無効化します。以下のコマンドを実行してください
sudo vim /etc/fstab # /swap.imgをコメントアウトするsudo swapoff -a確認のために下のコマンドを実行してください。うまくいっていれば、2 段目 Swap の項目がすべて 0 になっているはずです
free -hkubeadm,kubelet,kubectl インストール
まず、kubeadm などのインストールに必要なライブラリをインストールします
sudo apt-get updatesudo apt-get install -y apt-transport-https ca-certificates curl公開鍵ダウンロード
2024-01-23追記
旧リポジトリの利用が非推奨になったためコマンドを変更しました。詳細は以下のリンクを確認してください
https://kubernetes.io/blog/2023/08/31/legacy-package-repository-deprecation/
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpgkubernetes のリポジトリをリポジトリリスト追加しダウンロードできるようにします
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list主要なコンポーネントである kubelet、kubeadm、kubectl をインストールし、これらのパッケージが自動的にアップデートされないようにバージョンを固定します
sudo apt-get updatesudo apt-get install -y kubelet kubeadm kubectlsudo apt-mark hold kubelet kubeadm kubectlkubectl をすべて外部のホストから利用する方は kubectl を取り除いておいてください
CRI-O インストール
cri-o/install.md at main · cri-o/cri-o (github.com)
上記の公式ドキュメントにしたがって進めていきます。ここから管理者権限が必要な部分が多いので管理者に昇格します
sudo su次に、以下のコマンドを実行して CRI-O をインストールします。ただし、export で設定している値は各自の環境に合わせて変更してください。
# このバージョンは以下を参照して任意のものに変えてください# https://cri-o.github.io/cri-o/export VERSION=1.27# https://github.com/cri-o/cri-o/blob/main/install.md#apt-based-operating-systemsexport OS=xUbuntu_22.04
echo "deb [signed-by=/usr/share/keyrings/libcontainers-archive-keyring.gpg] https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.listecho "deb [signed-by=/usr/share/keyrings/libcontainers-crio-archive-keyring.gpg] https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list
mkdir -p /usr/share/keyringscurl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | gpg --dearmor -o /usr/share/keyrings/libcontainers-archive-keyring.gpgcurl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/Release.key | gpg --dearmor -o /usr/share/keyrings/libcontainers-crio-archive-keyring.gpg
apt-get updateapt-get install cri-o cri-o-runccri-o/docs/crio.conf.5.md at main · cri-o/cri-o · GitHub
image/docs/containers-registries.conf.5.md at main · containers/image · GitHub
CRI-O はデフォルトの設定ではレジストリ名を与えられなかった際、docker.ioとquay.ioを確認します。
プライベートレジストリなどを運用している方はここで設定を変更すると良いと思います。
詳細は上記ドキュメントを参照してください。
次に、CRI-O がデフォルトで持っている CNI を削除します。このステップが本当に必要かどうかはまだ調査中ですが、試行錯誤の過程で、このステップをスキップすると外部 DNS への接続が失敗する事例が発生しました。詳細が分かり次第、追記します。
rm -rf /etc/cni/net.d/*最後に CRI-O を起動します
sudo systemctl daemon-reloadsudo systemctl enable criosudo systemctl start crio正常に起動しているか確認します。RuntimeReadyの項目が true であれば問題ないと思われます
crictl info
ここまでで VM 共通の設定が完了したので VM をシャットダウンしてください
クラスター作成
先ほど作成した VM をクローンします。私は計 4 個クローンしましたが、各自のマシンスペックに合わせて個数を調整してください。 クローン完了後 kubeadm が動作するために必要な条件を満たすため、各ノードに入り固定 IP の設定と hostname をすべて異なるものになるように変更します。 詳細は以下ドキュメントを確認してください。
固定 IP の変更は/etc/netplan以下の yaml を書き換えることで行えます。
sudo vim /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'network: ethernets: ens18: dhcp4: false addresses: - 192.168.1.150/24 # ここを各自に合わせて変更 routes: - to: default via: 192.168.1.1 # 環境にあった値にしてください nameservers: addresses: - 192.168.1.1 # 環境にあった値にしてください version: 2hostname は以下コマンドで変更できます。
sudo hostnamectl hostname new-hostnameここまで完了したら設定を読み込むため再起動しておきます
rebootkubeadm を使用したクラスターの作成 | Kubernetes
コントロールプレーンの初期化をします。ここで指定する--apiserver-advertise-addressにはコントロールプレーンのアドレスまたはドメイン名です。
--pod-network-cidrはクラスター内の Pod に割り振られるネットワーク帯です。もし10.10.0.0/16がすでに利用されている場合は別のものに変えてください。
sudo kubeadm init --apiserver-advertise-address=192.168.1.150 --pod-network-cidr=10.10.0.0/16この時表示されるkubeadm joinコマンドはメモしておきます
kubeadm join 192.168.1.150:6443 --token xxxx \ --discovery-token-ca-cert-hash sha256:xxxx表示されているコマンド通り kubectl を動作させるためのファイルを持ってきます
mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config完了後、先ほどメモしたkubeadm joinコマンドを各 node で実行します。
実行したら、コントロールプレーンで以下のコマンドを実行し正しく追加できているか確認します。
kubectl get nodeCalico インストール
Pod 間の通信を管理する CNI としてCalicoをインストールします。基本的に上記の公式ドキュメントにしたがって進めます。
まず Calico のオペレーターを追加します
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml次に設定ファイルをダウンロードします
curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml -O上記ファイルの ipPools のcidrをkubeadm init時の--pod-network-cidrに書き換え、その後設定ファイルを適用します
spec: # Configures Calico networking. calicoNetwork: # Note: The ipPools section cannot be modified post-install. ipPools: - blockSize: 26 cidr: 10.10.0.0/16 # ここを書き換えるkubectl create -f custom-resources.yamlコンテナーが作成されるまで待ちます。
watch kubectl get -A all1 台のみでクラスターを構成する場合は、コントロールプレーンに Pod が割り当てられるようにします。 これは、コントロールプレーンのノードに対するスケジューリング制約を削除することで実現します。ただし、複数のノードがある場合はこの操作は不要です。
Taint と Toleration | Kubernetes
kubectl taint nodes --all node-role.kubernetes.io/control-plane-kubectl taint nodes --all node-role.kubernetes.io/master-動作チェック
ここについては実施しなくても問題ないと思います
毎回 Proxmox の VM に接続するのは面倒なので config ファイルを開発用 PC に持ってきます。
持ってきた config と現在の config をマージします。ここは以下の stackoverflow を参考にしました。
出力された内容を確認し、問題がなさそうであればこれを~/.kube/configに配置します
kubernetes - How to merge kubectl config file with ~/.kube/config? - Stack Overflow
export KUBECONFIG=~/tmp.config:~/.kube/configkubectl config view --flatten
# 良さそうならkubectl config view --flatten > ~/.kube/configコンテキストを確認して、先ほど作成したクラスターのものに変えます。 (デフォルトだと kubernetes-admin@kubernetes 的な名前でしたがあまりにも無骨なので変えました)
kubectl config get-contextsCURRENT NAME CLUSTER AUTHINFO NAMESPACE* docker-desktop docker-desktop docker-desktop home-kubernetes home-kubernetes home-kubernetes-adminkubectl config use-context home-kubernetesnode が取得できるか確認します
kubectl get nodes簡単な設定ファイルを作成してapplyします
sample-deploy.yaml
apiVersion: apps/v1kind: Deploymentmetadata: name: nginx-deploymentspec: selector: matchLabels: app: nginx replicas: 1 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80
---apiVersion: v1kind: Servicemetadata: name: nginx-service labels: app: nginxspec: ports: - port: 80 protocol: TCP selector: app: nginxkubectl apply -f sample-deploy.yamlポート転送してアクセスできるか確かめます。これにより、localhostの 8080 ポートが nginx サービスの 80 ポートにアクセスできるようになります
kubectl port-forward services/nginx-service 8991:80実際にhttp://localhost:8080にアクセスして nginx の Welcome ページが表示されれば問題ないと思います
最後にこれを立ち下げます
kubectl delete -f sample-deploy.yaml終わりに
以上で、Proxmox 上に Kubernetes クラスターを構築する手順をご紹介しました。 Calico のインストールの際に少し触れましたが、試行錯誤段階では外部ドメイン名が解決されないという問題が起きていました。 これについて、私の理解が浅いことが原因の 1 つだと思います。
明日以降、同様の現象がどうしたら起きるのか調査し、自分の理解を深めたいと思います。
ここまでお読みいただき、ありがとうございました。