USBスティックSSDに、Fedora CoreOSをプロビジョニングしまして。
Raspberry Pi 4を3台使用して、クラスタを構築してみました。
microSDカードは使用しておらず、USBスティックSSDから起動したため、高速かつストレージの容量は大きく、構成もコンパクトです。(ストレージは分散ファイルシステムで無駄なく使用する予定です
今後、SSDの価格低下に伴い、よりストレージ容量の大きなクラスタが作成できそうです。
構築手順の覚書を記録しておこうと思います。
ちなみに、ansibleを使用させて頂いたため、構築はコマンド2個のみです。
その2個のコマンドを正しく動かすための、環境構築の覚書という感じです。
目次
Raspberry Pi 4 + Fedora CoreOSのKubernetesクラスタ構築手順の覚書
使用する機器
使用する機器はこちらの記事になります。
Raspberry Pi 4は3台使用します。こちらはKubernetesのノードであり、構築時に使用するAnsibleのマネージドノード(指令を受ける側)になります。OSはFedora CoreOSになります。
それ以外に、Raspberry Pi 3を1台使用します。役割は、Ansibleのコントロールノード(指令を出す側)と、CoreOSのブートメディア作成用、sshキー生成用、Kubernetesノードがインターネットに接続する際のプロキシサーバになります。こちらはFedora Linux Serverを使用しています。
ノードを増やしたい場合、コントロールノードから指令を出すことで、簡単に構成を変える事が可能です。各ノードのhostsファイルの調整等、細かい設定変更を自動で行ってくれます。
そのような理由から、クラスタノードとは別途、コントロールノード用に1台、Fedora Linuxマシンがあると、管理や拡張が容易になると思います。
構築はKubesprayを使用させて頂きました
Kubernetesの構築のはKubesprayを使用させて頂きました。
Kubesprayは、Ansibleを使用しています。
私が考える、Ansibleを使用するメリットは。
「Kubernetesを簡単にインストールしてくれる他に、SELinuxやFirewalldなど、Linuxのサブシステムを適切に調整してくれる。構成変更も容易。」
ところがポイントだと思います。
手動でインストールする場合、「SELinuxを無効に・・・」とか行いがちですが。(雑に
AnsibleはSELinuxの設定を含めて、Linux設定を適切に調整してくれるようです。
よって、構築時に大切なポイントとして、「Ansibleから各サブシステムを調整できるように、必要なパッケージを入れておく」ことが挙げられます。
マネージドノード(Raspberry Pi 4 指令を受ける側)の準備
ではいよいよ、構築手順を記録させて頂こうと思います。
Fedora CoreOSブート用Butane設定の作成
Raspberry Pi 4を3台使用しますが。それぞれ、ホスト名をIPアドレスを次のように設定したいと思います。
- node1 192.168.xxx.51
- node2 192.168.xxx.52
- node3 192.168.xxx.53
こちらを踏まえて、Fedora CoreOS起動時に使用するbutane設定ファイルを作成します。
こちらの記事になります。
3つのノード用に、それぞれ3つのbutaneとIgnitionファイルを作成します。
cat << EOF | tee config_node1.bu
variant: fcos
version: 1.5.0
ignition:
config:
merge:
- local: users.ign
- local: storage.ign
- local: network_node1.ign
- local: hostname_node1.ign
- local: timezone.ign
- local: keyboard.ign
# - local: swaponzram.ign
- local: enable-passwords.ign
- local: sysctl.ign
- local: reverse-path-filter.ign
- local: rpm-ostree-python.ign
# - local: container.ign
EOF
network.buとhostname.buをそれぞれコピーして、network_node1.bu、hostname_node1.buを別途作成した感じです。
cp network.bu network_node1.bu
cp hostname.bu hostname_node1.bu
cp network.bu network_node2.bu
#コピー後編集
vi network_node2.bu
cp hostname.bu hostname_node2.bu
#コピー後編集
vi hostname_node2.bu
cp network.bu network_node3.bu
#コピー後編集
vi network_node3.bu
cp hostname.bu hostname_node3.bu
#コピー後編集
vi hostname_node3.bu
cp config.bu config_node1.bu
#コピー後編集
vi config_node1.bu
cp config.bu config_node2.bu
#コピー後編集
vi config_node1.bu
cp config.bu config_node2.bu
#コピー後編集
vi config_node2.bu
IPアドレスとホスト名は、これで自動で設定されます。
コントロールノードでssh-keygenを実行、パブリックキーをusers.buファイルに記述
Ansibleのコントロールノード用のRaspberry Pi 3から、各ノードにsshログインできるように、コントロールノードにてssh-keygenを実行してキーを作成しておきます。
ssh-keygen -t ed25519 -C ""
cat ~/.ssh/id_ed25519.pub
# users.buに記載
users.buファイルのssh_authorized_keys:に作成したパブリックキーを指定しておきます。
これで、コントロールノードから、各マネージドノードにsshログインできるようになる=Ansibleでリモート設定が可能になります。
swap不要
注意点は、Kubernetesクラスタは、swapは作成しません。よってswaponzram.ignは使用しません。該当のmerge行はコメントにしておきましょう。
# - local: swaponzram.ign
ストレージ構成は適宜
ストレージ構成は、お好みのパーティション構成を指定しておいてください。
私の作成したストレージ構成は、ルートパーティションに64GB指定し、残りは/dev/sda5として別パーティションを確保しています。
これは分散ファイルシステムを後で作成することを考慮した構成です。
ストレージ構成を指定しない場合、ルートパーティションが自動で最大に拡張されます。
ノードで永続ボリューム(PV)を作成する場合、適宜構成を選択してください。
rpm-ostreeにて、pythonとlibselinux-python3をインストール
Ansibleを実行するためにpythonは必須です。それと、Ansibleからselinuxを設定できるようにlibselinux-python3をインストールしておく必要があります。
私の作成したbutaneでは、自動でインストールされるように、「rpm-ostree-python.bu」を作成し、config.buにてmergeしておきました。
# rpm-ostree-python.buにてパッケージ指定
ExecStart=/usr/bin/bash -c "/usr/bin/rpm-ostree install --reboot python pip libselinux-python3"
Fedora CoreOS起動後、しばらく待つと、「layer-python.service」が起動して、pythonとlibselinux-python3がインストールされて、自動再起動します。
Fedora CoreOSブートメディアの作成
以上のbutane設定を作成し、Ignitionにトランスパイルして、config_node1.ignファイルを作成しました。
同じように、config_node2.ign、config_node3.ignファイルを作成し、その後USBブートメディアを作成しました。
手順はこちらの記事になります。
各ノードでFedora CoreOSを起動し、しばらく待って自動再起動後(rpm-ostreeによるパッケージインストール完了)、AnsibleによるKuberneteのインストール準備ができたかたちになります。
コントロールノード(Raspberry Pi 3 指令を出す側)の準備
コントロールノード(Raspberry Pi 3)から、各マネージドノードにホスト名でアクセスできるように。/etc/hostsファイルに3行追加しておきます。
cat << EOF | sudo tee -a /etc/hosts
192.168.xxx.51 node1
192.168.xxx.52 node2
192.168.xxx.53 node3
EOF
ちなみに、各マネージドノード(Raspberry Pi 4)のhostsファイルは、Ansibleが自動で作成してくれます。
各ノードの起動・SSHログイン確認
Fedora CoreOSの起動とプロビジョニングが完了しましたら。
コントロールノード(Raspberr Pi 3)から、各マネージドノードにSSHログインできるかどうか確認しておきます。
ssh core@node1
ssh core@node2
ssh core@node3
上記のコマンドで、各ノードにログインできましたら、Ansibleによるプロビジョニングの準備ができていると思います。(あと各ノードにpython,libselinux-python3が入っていればOK
プロキシサーバ構成
それと、コントロールノードに、Squidをインストールしてプロキシサーバを構成しました。
手順はこちらの記事になります。
Ansibleでクラスタを構築している間、マネージドノードから直接インターネットへアクセスできなくなりました。
必要なファイルのダウンロードがエラーで止まってしまいます。
都度、各ノードの設定を変更するのも大変なため、プロキシサーバを準備して、ansibleの設定ファイル(all.yml)にてプロキシサーバを指定しておきます。(後述)
これにより、問題なく構築が進むようになりました。
AnsibleによるKubesprayプロビジョニング手順
Ansibleのコントロールノード・マネージドノードの準備ができたところで。ここから本格構築になります。
基本的に、マネージド・ノード(Raspberry Pi 4)は放置になります。(楽です
コントロール・ノード(Raspberry Pi 3)から、指令を出す感じです。コマンドは2つしかありませんが。途中で進行が止まる場合があるため、スクリプトを調整して進める感じです。
Ansibleのインストール
コントロールノード(Raspberry Pi 3)に、gitとAnsibleをインストールします。
sudo install -y git ansible python pip
AnsibleはRed Hatさんが開発ということで。Fedora Linuxでは問題なく使用できそうです。
Kubesprayのクローン
kubernetesをプロビジョニングするためのplaybookである、Kubesprayをクローンさせて頂きましょう。
git clone https://github.com/kubernetes-sigs/kubespray
cd kubespray/
pythonモジュールのインストール
sudo pip install -r requirements.txt
Ansibleで使用するpythonモジュールをインストールしておきましょう。
構成ファイルの作成
環境変数IPSは、作成するノードのIPアドレスを指定してください。
cp -rfp inventory/sample inventory/mycluster
# ノードのIPアドレスを記述
declare -a IPS=(192.168.xxx.51 192.168.xxx.52 192.168.xxx.53)
# hosts.yamlを確認
vi inventory/mycluster/hosts.yaml
# 設定作成
CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]}
# 設定確認
vi inventory/mycluster/group_vars/all/all.yml
vi inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
inventory/sampleディレクトリをコピー後。
IPSとCONFIG_FILE環境変数を指定して、pythonで構成(コンフィグ)ファイルを作成します。
今回、hosts.yamlファイルは既定ですが、ログを見ますと、node1とnode2がコントロール・プレーンに設定されるようです。
作成された、all.ymlとk8s-cluster.ymlファイルを確認しておきます。
私は、k8s-cluster.ymlはそのまま使用させて頂きましたが。
all.ymlファイルを編集し、プロキシサーバ経由でインターネットへアクセスできるようにしました。
all.ymlファイル編集 プロキシ設定を追加
all.ymlファイルのhttp_proxy、https_proxy行を有効にします。
ここではプロキシサーバのIPアドレス:ポート番号は「192.168.xxx.41:3128」になっています。適宜変更してください。
http_proxy: "http://192.168.xxx.41:3128"
https_proxy: "http://192.168.xxx.41:3128"
no_proxy: "localhost,127.0.0.1,localaddress"
クラスタのリセット
最初。–become-userにcoreを指定してしまい、うまく動かなくて悩みました。
Fedora CoreOSは、ログイン可能なユーザはcoreですが、管理者権限はrootで実行する必要があります。よって、ansibleを実行する場合、–userオプションにcore、–become-userオプションにroot指定が正解のようです。
ansible-playbook -i inventory/mycluster/hosts.yaml \
--user core --become --become-user=root \
reset.yml
reset.ymlをプロビジョニングして、各ノードを初期状態にします。
途中で「リセットしますか?」と聞かれます。
初期構築は「no」で大丈夫だと思います。「no」を入力すると、そこで処理が止まります。(failed)
続いてクラスタの構築に入りますが。
本当にクラスタをリセットして消したい場合
ちなみに、クラスタ構築後に、本当にリセットしてクラスタを消去したい場合は、次のコマンドでreset.ymlを実行しておきます。
ansible-playbook -i inventory/mycluster/hosts.yaml \
--user core --become --become-user=root \
reset.yml \
-e reset_confirmation=yes
途中で「yes」を入力してもfailedで進まなかったため、「reset_confirmation=yes」環境変数を追加して、強制的にyesが認識されるようにしたコマンドになります。
リセットが正常に完了すると、このようなメッセージが表示されます。
playbookの実行が完了したかどうかは、「failed=0」がポイントになります。各ノードのKubernetesを削除して、プレーンな状態に戻す事が可能です。
KubesprayでHelmやMetalLBをプロビジョニングしたい場合
Helmを一緒にインストールしてしまう場合は、コントロールプレーンにpython3-pyyamlをインストールしておく必要があるようです→Fedora CoreOSではインストールできませんでした。
# helmをインストールする場合、コントロールプレーンにpython3-pyyamlをインストール
sudo rpm-ostree install python3-pyyaml --reboot
# と思いましたが、Fedora CoreOSは未対応かもしれません
addons.ymlファイルを編集して、プロビジョニングの設定を行っておきます。
MetalLBを使用する場合、k8s-cluster.ymlを編集してkube_proxy_strict_arp:を設定しておきます。
# HelmやMetalLBをプロビジョニングする場合、事前に設定
vi inventory/mycluster/group_vars/k8s_cluster/addons.yml
vi inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
# kube_proxy_strict_arp: true
クラスタの構築コマンド(Calico使用)
構築を開始するコマンドは下記になります。既定の設定では、ネットワークプラグインはCalicoになるようです。他のプラグインを使用する場合は、次のセクションにて。
ansible-playbook -i inventory/mycluster/hosts.yaml --user core --become --become-user=root cluster.yml
こちらのコマンドで、構築が開始されますが。
デバッグログ、詳細を見たい場合は、-vvとか-vvvvオプションを追加して実行します。(豆
# 詳細な情報を知りたい場合
# ansible-playbook -i inventory/mycluster/hosts.yaml --user core --become --become-user=root -vv cluster.yml
# ansible-playbook -i inventory/mycluster/hosts.yaml --user core --become --become-user=root -vvvv cluster.ymlけ
基本的に、あとは放置します。(楽
すべての処理が実行されるのではなく、時折ignore(無視)が出る場合は問題ありません。
failed(失敗)が出ることなく、最後まで進めば終了ですが。
failedでplaybookが止まってしまう場合は、対応が必要になります。
クラスタの構築コマンド(Flannel使用)
MetalLBを使用したい場合など、ネットワークプラグインをFlannelに変えたい場合のオプションは以下のようです。
# Flannelを使用する環境変数追加
ansible-playbook -i inventory/mycluster/hosts.yaml --user core --become --become-user=root cluster.yml -e kube_network_plugin=flannel
MetalLBは、kubespayでクラスタと併せてインストール可能です。こちらの記事になります。playbook実行前に、yamlファイルを変えておく感じです。
クラスタの構築コマンド(Flannel使用・dnsループ対応)
上記のキャプチャ画面を見ると、nodelocaldnsが異常終了しています。
kubesprayによる、corednsとnodelocaldnsのデプロイの影響のようですが、まだ解決してない感じです。
playbookのオプションで、resolvconf_mode=noneを追加したところ、dnsループは解消されました。この状態でしばらくkubernetesを使ってみましたが、問題無さそうです。
ansible-playbook -i inventory/mycluster/hosts.yaml \
--user core --become --become-user=root \
cluster.yml \
-vvvv \
-e kube_network_plugin=flannel \
-e resolvconf_mode=none
flannelを使用してdnsエラーが出る場合は、こちらのオプションで様子を見ましょう。
クラスタ構築がfailedで止まる場合の対応
使用するコンポーネントのバージョンや、状況によると思いますが。
playbookが途中でfailedで止まった場合の覚書になります。
SELinuxエラー
Ansibleが、各ノードのSELinux設定を変更できず、エラーが出ました。
この場合、各ノードにlibselinux-python3をインストールして、pythonからselinxの設定を変更できるようにしました。
その他failed
Fedora CoreOSでは、rpm-ostreeによるパッケージインストール後、再起動する必要があります。その場合、構築中にfailedで失敗する必要があるため、再起動後にもう一度playbookを実行します。
確かに、playbookを何度か実行すると、次に進める場合もあるようです。
なにかファイル名が古いなど、場合によりkubesprayのymlを編集する必要がある場合もありましたが、kubesprayのバージョンアップが頻繁なため、更新されている可能性もあります。このため、ここに細かいところを記載するのはやめました。
まずは、kubesprayのサポート情報を見るほうが良いと思います。
構築終了
最終的に、failedがないログが表示されれば、構築完了かと思います。
コントロールプレーン(node1またはnode2)にssh接続して、クラスタの動作確認を行います。
クラスタ動作確認
kubectlコマンド実行準備
コントロールプレーンの一台、node1にて、kubectlコマンドが実行できるように、~/.kube/configを作成しました。
# node1で実行
rm -fr ~/.kube
mkdir -p ~/.kube
sudo cp /etc/kubernetes/admin.conf ~/.kube/config
sudo chown core:core ~/.kube/config
kubectl get nodes
各ノードが構成されて、ステータスがすべて「Ready」準備完了の状態を確認できました。
もしもこのような状態にならない場合は。
構築が最後まで完了していない可能性があります。再度、ansible-playbookを実行して、構築を進めてみてください。
いちどreset.ymlでリセットするのも手かもしれません。
ansibleのymlファイルは、構築の手順が記載されているわけではなく、「構築後あるべき姿」が記載されています。
playbookを再実行した場合、設定済みの項目は無視され、あるべき姿になるまで、設定を調整してくれる動きになるようです。
私も、構築中に何度かエラーが出ましたが、再実行で進み、構築まで5回ほどplaybookを実行しました。
実際に、kubesprayで構築→リセット→構築を行ってみました。
ノードを再起動した場合など、STATUSがNotReadyのノードがあったりしましたが、kubesprayでリセットして入れ直すと、クリーンな環境でノードがリセットされて、Readyに戻るのは、次に使うことを考えると、安心感があります。
IgnitionでFedora CoreOSをプロビジョニングしたため、正直、CoreOSを入れ直す(ブートメディアの作り直し)のも、それほど大変ではありませんが。クラスタを入れ直したい場合は、reset.ymlを実行して戻すレベルで、十分に環境がきれいになるため、CoreOSのブートメディアの作り直しは行わずに済んでいます。(SSDの寿命に優しい
ノードを追加したい場合などは、ymlファイルを変更後、playbookを再実行すれば、新しいノードのSELinuxの設定や/etc/hostsファイルの設定等、細かいLinuxの設定も含めて追加してくれるのは、かなり実用的かと思います。
使い方の理解が浅いため、次はクラスタの使い方の勉強に進みたいと思います。