☀️

お家KubernetesをProxmoxで作り直した

createdAt
2023-07-08
updatedAt
2024-01-23
reading time
11 min read

経緯

以前の記事ででお家 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 のみ有効にし、それ以外はデフォルトで設定しました。 この部分については各自の環境に合わせて調整してください。

VM設定

作成が完了したら、パッケージを更新しておきます

Terminal window
sudo apt update
sudo apt upgrade -y

IPv4 フォワーディング有効化

コンテナランタイム | Kubernetes

以下のコマンドを実行します。

Terminal window
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# この構成に必要なカーネルパラメーター、再起動しても値は永続します
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 再起動せずにカーネルパラメーターを適用
sudo sysctl --system

正直何をしているか全然わかっていないので、周りの詳しい方に聞いたほうが良いと思います。一応 ChatGPT に聞いてみたら下のように返してきました

ChatGPTに聞いた

このコマンドを実行して必要なモジュールが正しくロードされていることを確認します

Terminal window
lsmod | grep br_netfilter
lsmod | grep overlay

swap の無効化

kubeadm のインストール | Kubernetes

前提条件として必要なので swap を無効化します。以下のコマンドを実行してください

Terminal window
sudo vim /etc/fstab # /swap.imgをコメントアウトする
sudo swapoff -a

確認のために下のコマンドを実行してください。うまくいっていれば、2 段目 Swap の項目がすべて 0 になっているはずです

Terminal window
free -h

kubeadm,kubelet,kubectl インストール

kubeadm のインストール | Kubernetes

まず、kubeadm などのインストールに必要なライブラリをインストールします

Terminal window
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl

公開鍵ダウンロード

2024-01-23追記
旧リポジトリの利用が非推奨になったためコマンドを変更しました。詳細は以下のリンクを確認してください
https://kubernetes.io/blog/2023/08/31/legacy-package-repository-deprecation/

Terminal window
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

kubernetes のリポジトリをリポジトリリスト追加しダウンロードできるようにします

Terminal window
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 をインストールし、これらのパッケージが自動的にアップデートされないようにバージョンを固定します

Terminal window
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

kubectl をすべて外部のホストから利用する方は kubectl を取り除いておいてください

CRI-O インストール

cri-o/install.md at main · cri-o/cri-o (github.com)

上記の公式ドキュメントにしたがって進めていきます。ここから管理者権限が必要な部分が多いので管理者に昇格します

Terminal window
sudo su

次に、以下のコマンドを実行して CRI-O をインストールします。ただし、export で設定している値は各自の環境に合わせて変更してください。

Terminal window
# このバージョンは以下を参照して任意のものに変えてください
# 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-systems
export 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.list
echo "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/keyrings
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | gpg --dearmor -o /usr/share/keyrings/libcontainers-archive-keyring.gpg
curl -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 update
apt-get install cri-o cri-o-runc

cri-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.ioquay.ioを確認します。 プライベートレジストリなどを運用している方はここで設定を変更すると良いと思います。 詳細は上記ドキュメントを参照してください。

次に、CRI-O がデフォルトで持っている CNI を削除します。このステップが本当に必要かどうかはまだ調査中ですが、試行錯誤の過程で、このステップをスキップすると外部 DNS への接続が失敗する事例が発生しました。詳細が分かり次第、追記します。

Terminal window
rm -rf /etc/cni/net.d/*

最後に CRI-O を起動します

Terminal window
sudo systemctl daemon-reload
sudo systemctl enable crio
sudo systemctl start crio

正常に起動しているか確認します。RuntimeReadyの項目が true であれば問題ないと思われます

Terminal window
crictl info

crictl info

ここまでで VM 共通の設定が完了したので VM をシャットダウンしてください

クラスター作成

先ほど作成した VM をクローンします。私は計 4 個クローンしましたが、各自のマシンスペックに合わせて個数を調整してください。 クローン完了後 kubeadm が動作するために必要な条件を満たすため、各ノードに入り固定 IP の設定と hostname をすべて異なるものになるように変更します。 詳細は以下ドキュメントを確認してください。

kubeadm のインストール | Kubernetes

固定 IP の変更は/etc/netplan以下の yaml を書き換えることで行えます。

Terminal window
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: 2

hostname は以下コマンドで変更できます。

Terminal window
sudo hostnamectl hostname new-hostname

ここまで完了したら設定を読み込むため再起動しておきます

Terminal window
reboot

kubeadm を使用したクラスターの作成 | Kubernetes

コントロールプレーンの初期化をします。ここで指定する--apiserver-advertise-addressにはコントロールプレーンのアドレスまたはドメイン名です。 --pod-network-cidrはクラスター内の Pod に割り振られるネットワーク帯です。もし10.10.0.0/16がすでに利用されている場合は別のものに変えてください。

Terminal window
sudo kubeadm init --apiserver-advertise-address=192.168.1.150 --pod-network-cidr=10.10.0.0/16

この時表示されるkubeadm joinコマンドはメモしておきます

Terminal window
kubeadm join 192.168.1.150:6443 --token xxxx \
--discovery-token-ca-cert-hash sha256:xxxx

表示されているコマンド通り kubectl を動作させるためのファイルを持ってきます

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

完了後、先ほどメモしたkubeadm joinコマンドを各 node で実行します。 実行したら、コントロールプレーンで以下のコマンドを実行し正しく追加できているか確認します。

Terminal window
kubectl get node

Calico インストール

Install Calico networking and network policy for on-premises deployments | Calico Documentation (tigera.io)

Pod 間の通信を管理する CNI としてCalicoをインストールします。基本的に上記の公式ドキュメントにしたがって進めます。 まず Calico のオペレーターを追加します

Terminal window
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/tigera-operator.yaml

次に設定ファイルをダウンロードします

Terminal window
curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/custom-resources.yaml -O

上記ファイルの ipPools のcidrkubeadm 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 # ここを書き換える
Terminal window
kubectl create -f custom-resources.yaml

コンテナーが作成されるまで待ちます。

Terminal window
watch kubectl get -A all

1 台のみでクラスターを構成する場合は、コントロールプレーンに Pod が割り当てられるようにします。 これは、コントロールプレーンのノードに対するスケジューリング制約を削除することで実現します。ただし、複数のノードがある場合はこの操作は不要です。

Taint と Toleration | Kubernetes

Terminal window
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
kubectl taint nodes --all node-role.kubernetes.io/master-

動作チェック

ここについては実施しなくても問題ないと思います

毎回 Proxmox の VM に接続するのは面倒なので config ファイルを開発用 PC に持ってきます。

Terminal window
scp [email protected]:/home/username/.kube/config ./tmp.config

持ってきた config と現在の config をマージします。ここは以下の stackoverflow を参考にしました。 出力された内容を確認し、問題がなさそうであればこれを~/.kube/configに配置します

kubernetes - How to merge kubectl config file with ~/.kube/config? - Stack Overflow

Terminal window
export KUBECONFIG=~/tmp.config:~/.kube/config
kubectl config view --flatten
# 良さそうなら
kubectl config view --flatten > ~/.kube/config

コンテキストを確認して、先ほど作成したクラスターのものに変えます。 (デフォルトだと kubernetes-admin@kubernetes 的な名前でしたがあまりにも無骨なので変えました)

Terminal window
kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* docker-desktop docker-desktop docker-desktop
home-kubernetes home-kubernetes home-kubernetes-admin
Terminal window
kubectl config use-context home-kubernetes

node が取得できるか確認します

Terminal window
kubectl get nodes

簡単な設定ファイルを作成してapplyします

  • sample-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
app: nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
app: nginx
Terminal window
kubectl apply -f sample-deploy.yaml

ポート転送してアクセスできるか確かめます。これにより、localhostの 8080 ポートが nginx サービスの 80 ポートにアクセスできるようになります

Terminal window
kubectl port-forward services/nginx-service 8991:80

実際にhttp://localhost:8080にアクセスして nginx の Welcome ページが表示されれば問題ないと思います 最後にこれを立ち下げます

Terminal window
kubectl delete -f sample-deploy.yaml

終わりに

以上で、Proxmox 上に Kubernetes クラスターを構築する手順をご紹介しました。 Calico のインストールの際に少し触れましたが、試行錯誤段階では外部ドメイン名が解決されないという問題が起きていました。 これについて、私の理解が浅いことが原因の 1 つだと思います。

明日以降、同様の現象がどうしたら起きるのか調査し、自分の理解を深めたいと思います。

ここまでお読みいただき、ありがとうございました。