🏖️

Kubernetesクラスタ構築 - おうちでGitOpsシリーズ投稿2/6

2023/06/28に公開

こちらはおうちラボでGitOpsシリーズの2つ目のポストです。

前回のポストでは一体このシリーズで何を作っていくかのイントロと流れの紹介、またDockerでDNSサーバ、リバースプロキシサーバ、そしてGitLabをセットアップしました。

今回はKubernetesクラスタをセットアップしていきます。バージョンは私がここ最近作った時点での最新、v1.27.1です。最初にKubernetesクラスタのコントロールプレーンとして使用するノードとしてRaspberry Pi 4、そしてクラスタに参加させるノードとしてRaspberry Pi 4をもう一台と、Debian11を入れたファンレスミニPCそれぞれでの作業を紹介していきます。

なお本シリーズではノードはそれぞれ、rpi4bp, rpi4, d11と呼んでいきます。

本シリーズのお約束

  • Kubernetes Cluster on 3 nodes (2 raspberry pi4 - arm64, and 1 amd64 fanless mini PC)
    • flannel for networking
    • flux as a GitOps tool
    • metallb for LoadBalancer service type implementation
  • 1 or more machine running Docker
    • serving GitLab (Used for GitOps central repository)
    • serving Nginx (Reverse proxy to provide access to GitLab and other web services to be created on Kubernetes Cluster)
    • serving Unbound (DNS resolver for machines on LAN)
  • public DNS domain + SSL/TLS certification (for example, Let's Encrypt) recommended
    • they are all mydomain.net in the series
    • replace mydomain.net with your own DNS domain to follow through

More on Docker - Series Top: Dockerで作るおうちLAN遊び場 シリーズ1/7

Interested in getting your own DNS domain?

セットアップ

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/

やることとしてはKubernetesのドキュメント通りですが、次の通りとなります。

  • (Raspberry Pi ImagerなどでOSインストールは完了しておりsshでログインできる状態まで持ってきている前提)
  • 固定IPアドレス設定
  • DNS設定
  • swap無効
  • システムのネットワーク設定
  • containerdインストールと設定
  • kubeadm, kubelet, kubectlインストール
  • kubeadmでクラスタ立ち上げ
    • 2, 3台目はkubeadmでクラスタに参加
  • ネットワークプラグインとしてflannelをインストール

固定IPアドレスとDNS設定

Raspberry Piはデスクトップ環境などの入っていないLiteバージョンを入れています。sudo vi /etc/dhcpcd.confで設定を更新し、リブートすれば設定できます。

内容に関しては、元々ファイル内でコメントアウトされている例を参考にできるかと思いますが、例えばLANのサブネットが192.168.1.0/24でルータ・ゲートウェイのIPアドレスが192.168.1.1とした場合、以下のようになります。また、このシリーズでは192.168.1.55でUnbound DNSサービスをDockerコンテナとして走らせている前提ですので、DNSサーバも指定します。

なおDNSサーバは2台以上あるのが理想的です。もし他のノードでもDNSサーバを立ち上げている場合はスペース区切りでstatic domain_name_servers=192.168.1.55 192.168.1.54のように記載しましょう。

domain_searchは単に名前解決するときに利用するサーチサフィックスです。本シリーズではなくても問題ないですし、好きなように設定しましょう。

ちなみにrpi4bpで192.168.1.56、rpi4では192.168.1.57としていきます。IPアドレスは重複しないように好きなように割り当ててください。

interface eth0
static ip_address=192.168.1.56/24
static routers=192.168.1.1
static domain_name_servers=192.168.1.55
static domain_search=mydomain.net

なおOSが異なるd11は別のファイルで設定します。

まず固定IPアドレスですが、sudo vi /etc/network/interfacesで以下のように編集します。元々iface enp2s0 inet dhcpのような行が#でコメントアウトされずにあると思います。その行はコメントアウトして残しても削除してもどちらでも良いです。

# The primary network interface
allow-hotplug enp2s0
#iface enp2s0 inet dhcp
iface enp2s0 inet static
address 192.168.1.58
netmask 255.255.255.0
gateway 192.168.1.1

次にDNSサーバの設定は、sudo vi /etc/resolv.confで以下のように編集します。

domain mydomain.net
search mydomain.net
nameserver 192.168.1.55

swap無効

ここからは公式のドキュメント通りに行くと思います。あらゆるところに同じことを書いたドキュメント、ブログポストがあると思いますが、このポストでもセットアップ手順を一から書いていきます。

まずswap無効ですが、やり方がシステムごとに異なると思いますが、Raspberry Pi 4もDebian 11を入れたミニPCも次の手順でswap無効化できました。

grubでnoresumeを追加しsudo update-grubで反映するのと、systemctl --type swapでsystemd上で見えるswapを確認し、それをmaskするという2点です。あともしfstabにswap関連の記載があればコメントアウトしたらよいと思います。

sudo vi /etc/default/grub
# add "noresume" in GRUB_CMDLINE_LINUX_DEFAULT
# GRUB_CMDLINE_LINUX_DEFAULT="quiet noresume"
sudo update-grub

# find swap on systemd and mask it
systemctl --type swap
sudo systemctl mask dev-sda3.swap

# comment out an entry for swap in fstab if present
sudo vi /etc/fstab
sudo shutdown -r now

システムのネットワーク設定

ドキュメントはswap無効化などの要件の次はcontainer runtimeをインストールする流れですが、前提として必要となる設定の有効化をします。

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# sysctl params required by setup, params persist across reboots
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

# Apply sysctl params without reboot
sudo sysctl --system

containerdなどのインストールと設定

続いてcontainerd, runc, CNI pluginsをインストール、設定します。下のコードブロック一つに全てまとめてしまっていますが、やっていることは次の通りです。ちなみにRaspberry Pi、d11ともに共通の流れでできます。ダウンロードするファイルについては最新を選べば良いと思います。CPUアーキテクチャに注意して選択しましょう。私はRasbperry Pi 2台にはarm64、d11についてはamd64とついているファイルを選択しました。

  • ホームディレクトリにtmp (~/tmp)を用意してそこでファイルをダウンロード
  • containerdのダウンロード、解凍、daemonとして有効化
  • runcのダウンロードとインストール
  • CNIプラグインのダウンロード、/opt/cni/binディレクトリ作成、ダウンロード物をそのディレクトリに解凍
  • containerdのデフォルトコンフィグをひとまず~/tmp/config.toml.defaultとして出力し、containerd、runcオプションのところでSystemdCgroup=trueとなるよう変更
  • 用意できたcontainerdのコンフィグファイルを/etc/containerd/config.tomlとして保存し、サービスリスタート
mkdir ~/tmp
cd ~/tmp

# download and install containerd
curl -LO https://github.com/containerd/containerd/releases/download/v1.7.1/containerd-1.7.1-linux-arm64.tar.gz
sudo tar Cxzvf /usr/local containerd-1.7.1-linux-arm64.tar.gz
sudo systemctl daemon-reload
sudo systemctl enable --now containerd

# download and install runc
curl -LO https://github.com/opencontainers/runc/releases/download/v1.1.7/runc.arm64
sudo install -m 755 runc.arm64 /usr/local/sbin/runc

# download and install CNI plugins
curl -LO https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-arm64-v1.3.0.tgz
sudo mkdir -p /opt/cni/bin
sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-arm64-v1.3.0.tgz

# configure containerd
# first, generate default config at ~/tmp/config.toml.default
containerd config default > config.toml.default
# and then edit one line as described below
vi config.toml.default
## find section 
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
## and find "SystemdCgroup = false", and change it to true

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  ...
  ...
  SystemdCgroup = true
  
# and then cp this file to the containerd config directory
sudo cp config.toml.default /etc/containerd/config.toml
# restart containerd
sudo systemctl restart containerd

kubeadm, kubelet, kubectlインストール

ではKubernetes関連パッケージをインストールしていきます。先にリンクを貼った公式のドキュメントに記載しているもの、そのまんまです。パッケージマネージャaptでインストールするための下準備、インストール、そして平時のapt upgradeなどでバージョンアップされないようホールドするという手順が以下です。

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

curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg

echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

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

kubeadmでクラスタ立ち上げ

いよいよKubernetesクラスタの立ち上げです。

Control-planeとするノードではkubeadm init、他のクラスタ構成ノードはkubeadm joinしていきます。

私の環境ではrpi4bpをcontrol-planeとするので、そのノードで以下のコマンドを実行します。ネットワークプラグインにはflannelを使うのですが、そのデフォルト設定となっているpod用のネットワークは10.244.0.0/16なので、それを指定するためのオプションが追加されています。

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

いろいろ出力されますが、注目してほしいのは2点です。まずはsudoせずともKubernetes関連のコマンドを実行できるようにするためのコマンドが次の通りです。

To start using your cluster, you need to run the following as a regular user:

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

2つ目は、他のノードでkubeadm joinするためのコマンドについてです。これをKubernetesクラスタに参加させるノードで実行しましょう。

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join {ipaddr of the control-plane node}:6443 --token {tokenstring} \
	--discovery-token-ca-cert-hash sha256:{cacerthashstring}

ネットワークプラグインとしてflannelをインストール

この時点では、control-planeでkubectl get nodesと実行すると全ノードnot readyとなっていると思います。クラスタが機能するのにもう一つ必要なものがネットワークプラグインです。ちなみにkubectl get pods -Aで現時点で動いているpodが確認できます。

flannelというネットワークプラグインのインストールには以下のコマンドをcontrol-planeで実行しましょう。これだけでflannelのセットアップが完了します。

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

あらためてkubectl get nodesとすると若干時間はかかるかもしれませんが、ほどなくすべてreadyとなっているでしょう。再度kubectl get pods -Aを実行するとflannel関連のpodが作られているのが確認できます。

完成!!

これでKubernetesクラスタの完成です!次回はGitOpsでこのKubernetesクラスタを使っていくためのセットアップを進めていきます。

Discussion