🌟

自宅サーバーでHA構成のKubernetesクラスター構築してみた【Proxmox】

2023/03/21に公開

最近個人的にKubernetesを勉強する機運が高まったので、一から構築してみることとしました。
現在、家ではProxmoxクラスターを構築しています。ですのでそのProxmoxクラスター上にUbuntuサーバーを立て、さらにその上でKubernetesを構築してみたいと思います。せっかくUbuntu立て放題?なので、今回はきちんとHA構成で構築してみます。

構築する環境

今回はコントロールプレーン3台、ワーカーノード3台の構成でいこうと思います。
ステートフルなKubernetesのデータの保存場所であるetcd(エトセディーと読むらしい)は、外部ではなくコントロールプレーンノードと相乗りするパターン(積層コントロールプレーンノード)でいこうと思います。

また、本来であれば前段にロードバランサーが必要となってくるのですが、今回はNginxを利用したいと思います。

簡略化した図としてはこんな感じになりそうです。

Ubuntuサーバーの準備

あらかじめUbuntu 20.04のVMを6台構築します。VMよりLXCの方がメモリやCPUを節約できますが、あとで出てくるoverlayの利用がうまくいかないので避けました。ここらへんによるとホスト側のoverlayを使う方法もあるみたいですが、今回はシンプルにVMで作っちゃいたいと思います。(というかKubernetes構築でホスト側のことあんま考え始めたくない笑)

とりあえずKubernetes用Ubuntuのスペックは、

割り当て
memory 4GB
CPU 2Core
Storage 8GB

でいこうと思います。公式ドキュメントの最低要件を参考にしました。
冗長性を担保しつつ最低限の台数にするため、Master3台、Worker3台の計6台構築しました。

実際に構築するUbuntuはこのようになっています。

あとNginx用のUbuntuもLXCで立てておきました。これのスペックは特に初期設定からいじってません。

Nginxサーバーの準備

まずあらかじめNginxを用意しておきます。これは先ほどのNginx用のLXCで実行します。
これはコントロールプレーンがHA構成でなければ(コントロールプレーンが一台であれば)必要なさそうです。

Ubuntuのセットアップをしたのちに、NginxをInstallします。
(Ubuntuのセットアップは省略します…IPアドレスだけしっかり静的に設定しておくようにすれば大丈夫なはず)

$ sudo apt update && sudo apt -y upgrade
$ sudo apt install nginx

次にコントロールプレーンに転送するように設定します。

$ sudo vi /etc/nginx/nginx.conf

以下を追記します。server部分のIPはコントロールプレーンの今後設定する(予定)のIPアドレスにします。

stream {
  upstream kubernetes {
    least_conn;
    server 192.168.1.85:6443;
    server 192.168.1.86:6443;
    server 192.168.1.87:6443;
  }

  server {
    listen        6443;
    proxy_pass    kubernetes;
    proxy_timeout 10m;
    proxy_connect_timeout 1s;
  }
}

これでNginxの準備は完了です。

Kubernetesサーバーの準備

若干順番が前後しましたが、次にKubernetes用Ubuntu6台全てで作業していきます。最初はコントロールプレーンとワーカーノードで操作は一緒です。
まず以下を実行しておきます。

$ sudo apt update && sudo apt -y upgrade

containerdのInstall

現在KubernetesはDockerがコンテナランタイムとして非推奨なため、containerdをInstallします。公式を参考にしましたが、一応こちらにも手順を書いていこうと思います。

$ 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

以下のコマンドでモジュールが読み込まれていることを確認します。

$ lsmod | grep br_netfilter
$ lsmod | grep overlay

またnet.bridge.bridge-nf-call-iptablesnet.bridge.bridge-nf-call-ip6tablesnet.ipv4.ip_forwardカーネルパラメーターが1に設定されていることも確認します。

sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward

やっとここでcontainerdをInstallします。config.tomlも忘れずに作成しておきます。

$ sudo apt install -y containerd
$ sudo mkdir -p /etc/containerd
$ containerd config default | sudo tee /etc/containerd/config.toml

続いてsystemdを使うようにします。cgroupfsを使わないとエラーが発生するみたいな話もあったのですが、自分の環境では大丈夫でした。

sudo vi /etc/containerd/config.toml

SystemdCgroupの部分をtrueに変更してください。

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

kubeadm、kubelet、kubectlのインストール

こちらも公式ドキュメントに倣ってやっていきます。apt-keyの部分は少し変更しました。
また、cgroup-driverをsystemdにするのも忘れないようにします(ここ忘れててちょっと躓いた…)。

$ sudo apt-get install -y apt-transport-https ca-certificates curl
$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
$ cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
$ sudo apt-get update
$ sudo apt-get install -y kubelet kubeadm kubectl
$ sudo apt-mark hold kubelet kubeadm kubectl
$ cat << EOF | sudo tee /etc/default/kubelet
KUBELET_EXTRA_ARGS=--cgroup-driver=systemd
EOF
$ sudo systemctl daemon-reload
$ sudo systemctl restart kubelet

Kubernetesクラスターの構築

コントロールプレーンのセットアップ

ここまではコントロールプレーンとワーカーノードで操作が同じでしたが、ここから操作が変わってきます。
まずは一つのコントロールプレーンで以下を実行します。

$ sudo kubeadm init --control-plane-endpoint "192.168.1.90:6443" --upload-certs
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

kubeadm initを実行したときのkubeadm join二つは記録しておきます。

次にCNIのcalicoを作成します。こちらも公式ドキュメントを参考にしました。

$ curl https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml -O
$ kubectl create -f calico.yaml 

以下を実行してReadyになっていることを確認します(少し時間かかった)。

$ kubectl get pod -n kube-system -w

続いて他のコントロールプレーンで以下を実行します。kubeadm joinの部分はkubeadm initの出力を参考にしてください。

$ sudo kubeadm join 192.168.1.90:6443 ほげほげ...
$ mkdir -p $HOME/.kube
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

ワーカーノードのセットアップ

最後にワーカーノードもセットアップします。こちらもkubeadm initの出力を参考にしてください。

$ sudo kubeadm join 192.168.1.90:6443 ふがふが...

ワーカーノードとかを紐づけるのはめっちゃ簡単だった…

MacからkubectlでClusterを操作できるようにする

kubectlをMacBookにInstallして、MacBookからKubernetes Clusterにアクセスできるようにします。
以下をMacのTerminalで実行します。

$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl

次にControl Planeで以下を実行し、

$ kubectl config view --raw

出力内容をMacBook上の以下のファイルに書きます。(scpコマンドでもいいんですが…)

$ sudo vi $HOME/.kube/config

これでMacbook上でもkubectlが使えるようになったと思います。

最後に

今回はProxmox上にHA構成のKubernetesを構築してみました。
まだまだわからないことが多いですが、今後はこのKubernetesに自分のプロダクト(MyTalk, MyNote)を移したりして、遊んできたいと思います。

Discussion